2019-07-22 10:36:50 +00:00
import { decompose } from 'Engine/mecanisms/utils'
2019-08-26 15:37:05 +00:00
import variations from 'Engine/mecanisms/variations'
2019-11-28 11:03:23 +00:00
import { convertNodeToUnit } from 'Engine/nodeUnits'
2020-04-23 07:30:03 +00:00
import {
areUnitConvertible ,
convertUnit ,
inferUnit ,
serializeUnit
} from 'Engine/units'
2020-03-26 15:03:19 +00:00
import {
any ,
equals ,
is ,
map ,
max ,
mergeWith ,
min ,
path ,
pluck ,
2020-04-23 07:30:03 +00:00
reduce
2020-03-26 15:03:19 +00:00
} from 'ramda'
2019-07-09 10:14:42 +00:00
import React from 'react'
2019-11-28 11:03:23 +00:00
import { typeWarning } from './error'
2020-03-26 15:03:19 +00:00
import {
collectNodeMissing ,
defaultNode ,
evaluateArray ,
evaluateNode ,
evaluateObject ,
makeJsx ,
mergeAllMissing ,
parseObject
} from './evaluation'
2019-07-09 10:14:42 +00:00
import All è gement from './mecanismViews/Allègement'
import { Node , SimpleRuleLink } from './mecanismViews/common'
import InversionNum é rique from './mecanismViews/InversionNumérique'
import Product from './mecanismViews/Product'
2020-01-02 14:39:31 +00:00
import Recalcul from './mecanismViews/Recalcul'
2019-07-09 10:14:42 +00:00
import Somme from './mecanismViews/Somme'
import uniroot from './uniroot'
2019-11-28 11:03:23 +00:00
import { parseUnit } from './units'
2020-04-20 09:46:13 +00:00
import { EvaluatedRule } from './types'
2017-07-28 12:24:29 +00:00
2017-06-28 10:08:32 +00:00
export let mecanismOneOf = ( recurse , k , v ) = > {
2018-02-15 17:12:04 +00:00
if ( ! is ( Array , v ) ) throw new Error ( 'should be array' )
2017-07-09 17:42:45 +00:00
2018-01-08 15:07:26 +00:00
let explanation = map ( recurse , v )
2017-07-09 17:42:45 +00:00
2020-04-20 09:46:13 +00:00
let jsx = ( { nodeValue , explanation , unit } ) = > (
2017-07-13 19:55:59 +00:00
< Node
2017-06-28 10:08:32 +00:00
classes = "mecanism conditions list"
2017-10-24 16:25:31 +00:00
name = "une de ces conditions"
2017-07-13 19:55:59 +00:00
value = { nodeValue }
2020-04-20 09:46:13 +00:00
unit = { unit }
2020-02-27 09:35:38 +00:00
>
< ul >
{ explanation . map ( ( item , i ) = > (
< li key = { i } > { makeJsx ( item ) } < / li >
) ) }
< / ul >
< / Node >
2017-10-24 16:25:31 +00:00
)
2017-07-13 19:55:59 +00:00
2017-12-12 19:10:22 +00:00
let evaluate = ( cache , situationGate , parsedRules , node ) = > {
2018-01-03 15:54:19 +00:00
let evaluateOne = child = >
evaluateNode ( cache , situationGate , parsedRules , child ) ,
2018-01-08 15:07:26 +00:00
explanation = map ( evaluateOne , node . explanation ) ,
values = pluck ( 'nodeValue' , explanation ) ,
nodeValue = any ( equals ( true ) , values )
2017-10-24 16:25:31 +00:00
? true
2018-05-09 16:41:57 +00:00
: any ( equals ( null ) , values )
2018-11-15 15:21:53 +00:00
? null
: false ,
2018-04-13 09:44:49 +00:00
// Unlike most other array merges of missing variables this is a "flat" merge
// because "one of these conditions" tend to be several tests of the same variable
// (e.g. contract type is one of x, y, z)
2018-05-09 16:41:57 +00:00
missingVariables =
nodeValue == null
? reduce ( mergeWith ( max ) , { } , map ( collectNodeMissing , explanation ) )
: { }
2017-10-24 16:25:31 +00:00
2019-09-10 14:58:26 +00:00
return { . . . node , nodeValue , explanation , missingVariables }
2017-08-18 15:21:43 +00:00
}
2017-07-13 19:55:59 +00:00
return {
2017-08-18 15:21:43 +00:00
evaluate ,
2017-07-13 19:55:59 +00:00
jsx ,
explanation ,
category : 'mecanism' ,
name : 'une de ces conditions' ,
type : 'boolean'
2017-06-28 10:08:32 +00:00
}
}
2017-10-24 16:25:31 +00:00
export let mecanismAllOf = ( recurse , k , v ) = > {
2018-02-15 17:12:04 +00:00
if ( ! is ( Array , v ) ) throw new Error ( 'should be array' )
2017-07-09 17:42:45 +00:00
2018-01-08 15:07:26 +00:00
let explanation = map ( recurse , v )
2017-07-09 17:42:45 +00:00
2020-04-20 09:46:13 +00:00
let jsx = ( { nodeValue , explanation , unit } ) = > (
2017-07-13 19:55:59 +00:00
< Node
2017-07-09 17:42:45 +00:00
classes = "mecanism conditions list"
2017-10-24 16:25:31 +00:00
name = "toutes ces conditions"
2017-07-13 19:55:59 +00:00
value = { nodeValue }
2020-04-20 09:46:13 +00:00
unit = { unit }
2020-02-27 09:35:38 +00:00
>
< ul >
{ explanation . map ( ( item , i ) = > (
< li key = { i } > { makeJsx ( item ) } < / li >
) ) }
< / ul >
< / Node >
2017-10-24 16:25:31 +00:00
)
2017-07-13 19:55:59 +00:00
2017-12-12 19:10:22 +00:00
let evaluate = ( cache , situationGate , parsedRules , node ) = > {
2018-01-03 15:54:19 +00:00
let evaluateOne = child = >
evaluateNode ( cache , situationGate , parsedRules , child ) ,
2018-01-08 15:07:26 +00:00
explanation = map ( evaluateOne , node . explanation ) ,
values = pluck ( 'nodeValue' , explanation ) ,
nodeValue = any ( equals ( false ) , values )
2017-10-24 16:30:44 +00:00
? false // court-circuit
2018-05-09 16:41:57 +00:00
: any ( equals ( null ) , values )
2018-11-15 15:21:53 +00:00
? null
: true ,
2018-04-12 13:43:02 +00:00
missingVariables = nodeValue == null ? mergeAllMissing ( explanation ) : { }
2017-10-24 16:30:44 +00:00
2019-09-10 14:58:26 +00:00
return { . . . node , nodeValue , explanation , missingVariables }
2017-10-24 16:30:44 +00:00
}
2017-07-13 19:55:59 +00:00
return {
2017-10-24 16:30:44 +00:00
evaluate : evaluate ,
2017-07-13 19:55:59 +00:00
jsx ,
explanation ,
category : 'mecanism' ,
name : 'toutes ces conditions' ,
type : 'boolean'
2017-07-09 17:42:45 +00:00
}
2017-06-28 10:08:32 +00:00
}
2017-06-28 07:31:37 +00:00
2020-04-23 07:30:03 +00:00
let evaluateInversion = ( oldCache , situationGate , parsedRules , node ) = > {
// TODO : take applicability into account here
let inversedWith = node . explanation . inversionCandidates . find (
n = > situationGate ( n . dottedName ) != undefined
2019-01-10 17:47:39 +00:00
)
2020-04-23 07:30:03 +00:00
if ( ! inversedWith ) {
2018-01-03 15:54:19 +00:00
return {
2020-04-23 07:30:03 +00:00
. . . node ,
missingVariables : {
. . . Object . fromEntries (
node . explanation . inversionCandidates . map ( n = > [ n . dottedName , 1 ] )
) ,
[ node . explanation . ruleToInverse ] : 1
} ,
2018-01-03 15:54:19 +00:00
nodeValue : null
}
2020-04-23 07:30:03 +00:00
}
inversedWith = evaluateNode (
oldCache ,
situationGate ,
parsedRules ,
inversedWith
)
2019-01-08 21:38:04 +00:00
2020-04-23 16:56:16 +00:00
let inversionCache
function resetInversionCache() {
inversionCache = {
_meta : { . . . oldCache . _meta }
}
return inversionCache
}
2020-04-23 07:30:03 +00:00
const evaluateWithValue = n = >
evaluateNode (
2020-04-23 16:56:16 +00:00
resetInversionCache ( ) ,
2020-04-23 07:30:03 +00:00
dottedName = >
dottedName === node . explanation . ruleToInverse
2020-04-23 16:56:16 +00:00
? {
nodeValue : n ,
unit : parsedRules [ node . explanation . ruleToInverse ] . unit
}
2020-04-23 07:30:03 +00:00
: dottedName === inversedWith . dottedName
2019-04-12 08:26:57 +00:00
? undefined
2020-04-23 07:30:03 +00:00
: situationGate ( dottedName ) ,
2017-11-20 12:16:18 +00:00
parsedRules ,
2020-04-23 07:30:03 +00:00
inversedWith
2018-04-10 15:16:27 +00:00
)
2017-11-20 12:16:18 +00:00
2020-03-09 15:51:10 +00:00
// si fx renvoie null pour une valeur numérique standard, disons 2000, on peut
2017-11-20 12:16:18 +00:00
// considérer que l'inversion est impossible du fait de variables manquantes
// TODO fx peut être null pour certains x, et valide pour d'autres : on peut implémenter ici le court-circuit
2020-04-23 07:30:03 +00:00
const randomAttempt = evaluateWithValue ( 2000 )
const nodeValue =
randomAttempt . nodeValue === null
? null
: // cette fonction détermine l'inverse d'une fonction sans faire trop d'itérations
uniroot (
x = > {
const candidateNode = evaluateWithValue ( x )
return (
candidateNode . nodeValue -
2020-04-20 09:46:13 +00:00
// TODO: convertNodeToUnit migth return null or false
( convertNodeToUnit ( candidateNode . unit , inversedWith )
. nodeValue as number )
2020-04-23 07:30:03 +00:00
)
} ,
node . explanation . negativeValuesAllowed ? - 1000000 : 0 ,
100000000 ,
2020-04-20 09:46:13 +00:00
0.1 ,
10
2020-04-23 07:30:03 +00:00
)
2017-11-20 12:16:18 +00:00
2020-04-23 07:30:03 +00:00
if ( nodeValue === undefined ) {
oldCache . _meta . inversionFail = true
2020-04-23 16:56:16 +00:00
} else {
// For performance reason, we transfer the inversion cache
Object . entries ( inversionCache ) . forEach ( ( [ k , value ] ) = > {
oldCache [ k ] = value
} )
2020-04-23 07:30:03 +00:00
}
2020-04-21 13:49:48 +00:00
2017-11-20 12:16:18 +00:00
return {
2020-04-23 07:30:03 +00:00
. . . node ,
nodeValue : nodeValue ? ? null ,
explanation : {
. . . node . explanation ,
inversionFail : nodeValue === undefined ,
inversedWith
} ,
missingVariables : randomAttempt.missingVariables
2017-11-20 12:16:18 +00:00
}
}
export let mecanismInversion = dottedName = > ( recurse , k , v ) = > {
2020-04-23 07:30:03 +00:00
if ( ! v . avec ) {
throw new Error (
"Une formule d'inversion doit préciser _avec_ quoi on peut inverser la variable"
)
2017-11-20 12:16:18 +00:00
}
return {
2020-04-23 07:30:03 +00:00
evaluate : evaluateInversion ,
2020-03-24 11:21:29 +00:00
unit : v.unit é && parseUnit ( v . unit é ) ,
2020-04-23 07:30:03 +00:00
explanation : {
ruleToInverse : dottedName ,
inversionCandidates : v.avec.map ( recurse ) ,
negativeValuesAllowed : v [ 'valeurs négatives possibles' ] === 'oui'
} ,
2019-01-30 17:53:57 +00:00
jsx : InversionNum é rique ,
2017-11-20 12:16:18 +00:00
category : 'mecanism' ,
2019-01-30 17:53:57 +00:00
name : 'inversion numérique' ,
2017-11-20 12:16:18 +00:00
type : 'numeric'
}
}
2020-01-02 14:39:31 +00:00
export let mecanismRecalcul = dottedNameContext = > ( recurse , k , v ) = > {
2020-04-23 07:30:03 +00:00
let evaluate = ( cache , situationGate , parsedRules , node ) = > {
if ( cache . _meta . inRecalcul ) {
2020-04-21 13:49:48 +00:00
return defaultNode ( false )
2020-04-02 16:54:41 +00:00
}
2020-04-23 07:30:03 +00:00
const recalculCache = { _meta : { . . . cache . _meta , inRecalcul : true } } // Create an empty cache
const amendedSituation = map (
value = > evaluateNode ( cache , situationGate , parsedRules , value ) ,
node . explanation . amendedSituation
)
const amendedSituationGate = dottedName = > {
if ( ! ( dottedName in amendedSituation ) ) {
return situationGate ( dottedName )
}
return amendedSituation [ dottedName ]
}
2020-01-02 14:39:31 +00:00
2020-04-23 07:30:03 +00:00
const evaluatedNode = evaluateNode (
recalculCache ,
2020-01-02 14:39:31 +00:00
amendedSituationGate ,
parsedRules ,
2020-04-23 07:30:03 +00:00
node . explanation . recalcul
2020-01-02 14:39:31 +00:00
)
return {
2020-04-23 07:30:03 +00:00
. . . node ,
nodeValue : evaluatedNode.nodeValue ,
. . . ( evaluatedNode . temporalValue && {
temporalValue : evaluatedNode.temporalValue
} ) ,
unit : evaluatedNode.unit ,
2020-01-02 14:39:31 +00:00
explanation : {
2020-04-23 07:30:03 +00:00
recalcul : evaluatedNode ,
amendedSituation
}
2020-01-02 14:39:31 +00:00
}
}
2020-04-23 07:30:03 +00:00
const amendedSituation = Object . fromEntries (
Object . keys ( v . avec ) . map ( dottedName = > [
recurse ( dottedName ) . dottedName ,
recurse ( v . avec [ dottedName ] )
] )
)
const defaultRuleToEvaluate = dottedNameContext
const nodeToEvaluate = recurse ( v . r è gle ? ? defaultRuleToEvaluate )
2020-01-02 14:39:31 +00:00
return {
2020-04-23 07:30:03 +00:00
explanation : {
recalcul : nodeToEvaluate ,
amendedSituation
} ,
jsx : Recalcul ,
2020-01-02 14:39:31 +00:00
evaluate
}
}
2017-10-24 16:25:31 +00:00
export let mecanismSum = ( recurse , k , v ) = > {
2017-07-09 22:14:22 +00:00
let explanation = v . map ( recurse )
2017-06-28 10:08:32 +00:00
2020-03-12 17:40:44 +00:00
let evaluate = evaluateArray (
( x , y ) = > ( x === false && y === false ? false : x + y ) ,
false
)
2017-07-13 19:55:59 +00:00
return {
evaluate ,
2020-04-29 16:12:26 +00:00
jsx : Somme ,
2017-07-13 19:55:59 +00:00
explanation ,
category : 'mecanism' ,
name : 'somme' ,
2019-07-11 14:29:05 +00:00
type : 'numeric' ,
2019-12-05 23:15:15 +00:00
unit : inferUnit (
'+' ,
explanation . map ( r = > r . unit )
)
2017-06-28 10:08:32 +00:00
}
}
2018-02-14 16:50:47 +00:00
export let mecanismReduction = ( recurse , k , v ) = > {
let objectShape = {
assiette : false ,
2019-02-14 17:00:31 +00:00
abattement : defaultNode ( 0 ) ,
2019-05-21 13:41:47 +00:00
plafond : defaultNode ( Infinity ) ,
2019-02-14 17:00:31 +00:00
franchise : defaultNode ( 0 )
2018-02-14 16:50:47 +00:00
}
2019-11-28 11:03:23 +00:00
let effect = (
{ assiette , abattement , plafond , franchise , d é cote } ,
cache
) = > {
2020-03-11 14:25:57 +00:00
let v_assiette = assiette . nodeValue
2020-02-24 17:34:38 +00:00
if ( v_assiette == null ) return { nodeValue : null }
2019-11-28 11:03:23 +00:00
if ( assiette . unit ) {
try {
franchise = convertNodeToUnit ( assiette . unit , franchise )
plafond = convertNodeToUnit ( assiette . unit , plafond )
2020-04-23 07:30:03 +00:00
if ( serializeUnit ( abattement . unit ) !== '%' ) {
2019-11-28 11:03:23 +00:00
abattement = convertNodeToUnit ( assiette . unit , abattement )
}
if ( d é cote ) {
d é cote . plafond = convertNodeToUnit ( assiette . unit , d é cote . plafond )
d é cote . taux = convertNodeToUnit ( parseUnit ( '' ) , d é cote . taux )
}
} catch ( e ) {
typeWarning (
cache . _meta . contextRule ,
"Impossible de convertir les unités de l'allègement entre elles" ,
e
)
}
}
2018-02-22 18:47:27 +00:00
let montantFranchis é D é cot é =
2020-03-11 14:25:57 +00:00
franchise . nodeValue && v_assiette < franchise . nodeValue
2018-02-14 16:50:47 +00:00
? 0
: d é cote
2019-09-11 08:04:19 +00:00
? ( function ( ) {
2020-03-11 14:25:57 +00:00
let plafondD é cote = d é cote . plafond . nodeValue ,
taux = d é cote . taux . nodeValue
2018-02-14 16:50:47 +00:00
2019-09-11 08:04:19 +00:00
return v_assiette > plafondD é cote
2018-11-15 15:21:53 +00:00
? v_assiette
2019-05-21 13:41:47 +00:00
: max ( 0 , ( 1 + taux ) * v_assiette - taux * plafondD é cote )
2019-09-11 08:04:19 +00:00
} ) ( )
2018-11-15 15:21:53 +00:00
: v_assiette
2019-11-28 11:03:23 +00:00
const nodeValue = abattement
2020-03-11 14:25:57 +00:00
? abattement . nodeValue == null
2018-05-09 16:41:57 +00:00
? montantFranchis é D é cot é === 0
? 0
: null
2020-04-23 07:30:03 +00:00
: serializeUnit ( abattement . unit ) === '%'
2018-11-15 15:21:53 +00:00
? max (
0 ,
2019-06-11 17:26:33 +00:00
montantFranchis é D é cot é -
2020-03-11 14:25:57 +00:00
min (
plafond . nodeValue ,
2020-04-23 07:30:03 +00:00
( abattement . nodeValue / 100 ) * montantFranchis é D é cot é
2020-03-11 14:25:57 +00:00
)
)
: max (
0 ,
montantFranchis é D é cot é -
min ( plafond . nodeValue , abattement . nodeValue )
2018-11-15 15:21:53 +00:00
)
2018-02-22 17:00:44 +00:00
: montantFranchis é D é cot é
2019-11-28 11:03:23 +00:00
return {
nodeValue ,
2020-02-24 17:34:38 +00:00
unit : assiette.unit ,
explanation : {
2019-11-28 11:03:23 +00:00
franchise ,
plafond ,
abattement
}
}
2018-02-14 16:50:47 +00:00
}
let base = parseObject ( recurse , objectShape , v ) ,
2018-02-15 14:40:10 +00:00
explanation = v . d é cote
? {
. . . base ,
d é cote : map ( recurse , v . d é cote )
2018-05-09 16:41:57 +00:00
}
2018-02-15 14:40:10 +00:00
: base ,
2018-02-14 16:50:47 +00:00
evaluate = evaluateObject ( objectShape , effect )
return {
evaluate ,
2018-02-21 12:46:38 +00:00
jsx : All è gement ,
2018-02-14 16:50:47 +00:00
explanation ,
category : 'mecanism' ,
name : 'allègement' ,
2019-09-06 14:23:26 +00:00
type : 'numeric' ,
unit : explanation?.assiette?.unit
2018-02-14 16:50:47 +00:00
}
}
2017-10-24 16:25:31 +00:00
export let mecanismProduct = ( recurse , k , v ) = > {
if ( v . composantes ) {
2020-03-24 16:50:18 +00:00
//mécanisme de composantes. Voir mécanismes.md/composantes
2017-10-24 16:25:31 +00:00
return decompose ( recurse , k , v )
2017-06-29 06:51:40 +00:00
}
2017-07-30 11:51:22 +00:00
if ( v . variations ) {
2019-07-22 10:36:50 +00:00
return variations ( recurse , k , v , true )
2017-07-30 11:51:22 +00:00
}
2017-06-29 06:51:40 +00:00
2017-07-12 09:50:34 +00:00
let objectShape = {
2017-10-24 16:25:31 +00:00
assiette : false ,
2019-02-14 17:00:31 +00:00
taux : defaultNode ( 1 ) ,
facteur : defaultNode ( 1 ) ,
plafond : defaultNode ( Infinity )
2017-07-12 09:50:34 +00:00
}
2019-11-28 11:03:23 +00:00
let effect = ( { assiette , taux , facteur , plafond } , cache ) = > {
if ( assiette . unit ) {
try {
plafond = convertNodeToUnit ( assiette . unit , plafond )
} catch ( e ) {
typeWarning (
cache . _meta . contextRule ,
2020-03-11 13:08:41 +00:00
"Impossible de convertir l'unité du plafond du produit dans celle de l'assiette" ,
2019-11-28 11:03:23 +00:00
e
)
}
}
2020-04-23 07:30:03 +00:00
const mult = ( base , rate , facteur , plafond ) = >
2020-03-09 17:23:48 +00:00
Math . min ( base , plafond === false ? Infinity : plafond ) * rate * facteur
2020-04-09 15:12:36 +00:00
2020-04-23 07:30:03 +00:00
let nodeValue = [ taux , assiette , facteur ] . some ( n = > n . nodeValue === false )
2020-04-09 15:12:36 +00:00
? false
: [ taux , assiette , facteur ] . some ( n = > n . nodeValue === 0 )
? 0
: [ taux , assiette , facteur ] . some ( n = > n . nodeValue === null )
? null
: mult (
assiette . nodeValue ,
taux . nodeValue ,
facteur . nodeValue ,
plafond . nodeValue
)
2020-04-23 07:30:03 +00:00
let unit = inferUnit (
2019-11-28 11:03:23 +00:00
'*' ,
[ assiette , taux , facteur ] . map ( el = > el . unit )
)
2020-04-23 07:30:03 +00:00
if ( areUnitConvertible ( unit , assiette . unit ) ) {
nodeValue = convertUnit ( unit , assiette . unit , nodeValue )
unit = assiette . unit
}
2019-03-25 18:14:27 +00:00
return {
2019-11-28 11:03:23 +00:00
nodeValue ,
2020-02-24 17:34:38 +00:00
unit ,
explanation : {
plafondActif : assiette.nodeValue > plafond . nodeValue
2019-11-28 11:03:23 +00:00
}
2019-03-25 18:14:27 +00:00
}
2017-07-11 15:39:50 +00:00
}
2017-10-24 16:25:31 +00:00
let explanation = parseObject ( recurse , objectShape , v ) ,
evaluate = evaluateObject ( objectShape , effect )
2017-07-11 15:39:50 +00:00
2017-07-13 19:55:59 +00:00
return {
evaluate ,
2019-03-20 15:59:55 +00:00
jsx : Product ,
2017-07-13 19:55:59 +00:00
explanation ,
category : 'mecanism' ,
2020-03-11 13:08:41 +00:00
name : 'produit' ,
2019-07-11 14:29:05 +00:00
type : 'numeric' ,
2019-07-11 15:07:34 +00:00
unit : inferUnit (
'*' ,
[ explanation . assiette , explanation . taux , explanation . facteur ] . map (
el = > el . unit
)
)
2017-06-28 10:08:32 +00:00
}
}
2017-10-24 16:25:31 +00:00
export let mecanismMax = ( recurse , k , v ) = > {
2017-07-11 15:39:50 +00:00
let explanation = v . map ( recurse )
2017-06-28 10:08:32 +00:00
2020-04-23 07:30:03 +00:00
const max = ( a , b ) = > {
if ( a === false ) {
return b
}
if ( b === false ) {
return a
}
if ( a === null || b === null ) {
return null
}
return Math . max ( a , b )
}
2018-01-08 15:07:26 +00:00
let evaluate = evaluateArray ( max , Number . NEGATIVE_INFINITY )
2017-07-13 19:55:59 +00:00
2020-04-20 09:46:13 +00:00
let jsx = ( { nodeValue , explanation , unit } ) = > (
2017-07-13 19:55:59 +00:00
< Node
2017-06-28 10:08:32 +00:00
classes = "mecanism list maximum"
name = "le maximum de"
2017-07-13 19:55:59 +00:00
value = { nodeValue }
2020-04-20 09:46:13 +00:00
unit = { unit }
2020-02-27 09:35:38 +00:00
>
< ul >
{ explanation . map ( ( item , i ) = > (
< li key = { i } >
< div className = "description" > { v [ i ] . description } < / div >
{ makeJsx ( item ) }
< / li >
) ) }
< / ul >
< / Node >
2017-10-24 16:25:31 +00:00
)
2017-07-13 19:55:59 +00:00
return {
evaluate ,
jsx ,
explanation ,
type : 'numeric' ,
category : 'mecanism' ,
2019-10-24 12:58:41 +00:00
name : 'le maximum de' ,
unit : explanation [ 0 ] . unit
2017-06-28 10:08:32 +00:00
}
}
2017-10-24 16:25:31 +00:00
export let mecanismMin = ( recurse , k , v ) = > {
2017-07-30 21:50:36 +00:00
let explanation = v . map ( recurse )
2018-01-08 15:07:26 +00:00
let evaluate = evaluateArray ( min , Infinity )
2017-07-30 21:50:36 +00:00
2020-04-20 09:46:13 +00:00
let jsx = ( { nodeValue , explanation , unit } ) = > (
2017-07-30 21:50:36 +00:00
< Node
classes = "mecanism list minimum"
name = "le minimum de"
value = { nodeValue }
2020-04-20 09:46:13 +00:00
unit = { unit }
2020-02-27 09:35:38 +00:00
>
< ul >
{ explanation . map ( ( item , i ) = > (
< li key = { i } >
< div className = "description" > { v [ i ] . description } < / div >
{ makeJsx ( item ) }
< / li >
) ) }
< / ul >
< / Node >
2017-10-24 16:25:31 +00:00
)
2017-07-30 21:50:36 +00:00
return {
evaluate ,
jsx ,
explanation ,
type : 'numeric' ,
category : 'mecanism' ,
2019-06-19 09:54:47 +00:00
name : 'le minimum de' ,
unit : explanation [ 0 ] . unit
2017-07-30 21:50:36 +00:00
}
}
2018-09-06 14:45:50 +00:00
export let mecanismSynchronisation = ( recurse , k , v ) = > {
let evaluate = ( cache , situationGate , parsedRules , node ) = > {
let APIExplanation = evaluateNode (
cache ,
situationGate ,
parsedRules ,
node . explanation . API
)
2018-09-06 16:33:12 +00:00
2019-04-08 09:56:56 +00:00
let valuePath = v . chemin . split ( ' . ' )
2018-09-06 14:45:50 +00:00
let nodeValue =
2020-03-11 14:25:57 +00:00
APIExplanation . nodeValue == null
? null
: path ( valuePath , APIExplanation . nodeValue )
2019-04-08 09:56:56 +00:00
// If the API gave a non null value, then some of its props may be null (the API can be composed of multiple API, some failing). Then this prop will be set to the default value defined in the API's rule
let safeNodeValue =
2020-03-11 14:25:57 +00:00
nodeValue == null && APIExplanation . nodeValue != null
2019-04-08 09:56:56 +00:00
? path ( valuePath , APIExplanation . explanation . defaultValue )
: nodeValue
2018-09-06 16:33:12 +00:00
let missingVariables =
2020-03-11 14:25:57 +00:00
APIExplanation . nodeValue === null
? { [ APIExplanation . dottedName ] : 1 }
: { }
2018-09-06 14:45:50 +00:00
let explanation = { . . . v , API : APIExplanation }
2019-09-10 14:58:26 +00:00
return { . . . node , nodeValue : safeNodeValue , explanation , missingVariables }
2018-09-06 14:45:50 +00:00
}
return {
explanation : { . . . v , API : recurse ( v . API ) } ,
evaluate ,
2020-04-20 09:46:13 +00:00
jsx : function Synchronisation ( { explanation } ) {
2018-09-07 14:56:36 +00:00
return (
< p >
Obtenu à partir de la saisie < SimpleRuleLink rule = { explanation . API } / >
< / p >
)
} ,
2018-09-06 14:45:50 +00:00
category : 'mecanism' ,
name : 'synchronisation'
}
}
2019-05-15 14:31:33 +00:00
export let mecanismOnePossibility = dottedName = > ( recurse , k , v ) = > ( {
2019-05-14 11:52:23 +00:00
. . . v ,
'une possibilité' : 'oui' ,
evaluate : ( cache , situationGate , parsedRules , node ) = > ( {
. . . node ,
2019-05-15 14:31:33 +00:00
missingVariables : { [ dottedName ] : 1 }
2019-05-14 11:52:23 +00:00
} )
} )