2017-01-09 17:17:51 +00:00
import R from 'ramda'
2017-01-10 14:39:40 +00:00
import rules from './load-rules'
2017-01-19 15:27:27 +00:00
import removeDiacritics from './remove-diacritics'
import { findRuleByName , extractRuleTypeAndName } from './rules'
2017-01-20 10:52:39 +00:00
import { recognizeExpression } from './expressions'
2017-01-09 17:17:51 +00:00
2017-01-19 15:27:27 +00:00
// L'objectif de la simulation : quelles règles voulons nous calculer ?
let selectedRules = rules . filter ( rule =>
R . contains (
extractRuleTypeAndName ( rule ) . name ,
[ 'CIF CDD' , 'Indemnité de fin de contrat' ]
)
)
2017-01-09 17:17:51 +00:00
2017-01-10 18:22:44 +00:00
let knownVariable = ( situation , variableName ) => ( typeof situation ( variableName ) !== 'undefined' )
let deriveRule = situation => R . pipe (
R . toPairs ,
// Reduce to [variables needed to compute that variable, computed variable value]
R . reduce ( ( [ variableNames , result ] , [ key , value ] ) => {
2017-01-17 09:04:34 +00:00
if ( key === 'concerne' ) {
2017-01-10 18:22:44 +00:00
let [ variableName , evaluation ] = recognizeExpression ( value )
// Si cette variable a été renseignée
2017-01-17 09:04:34 +00:00
if ( knownVariable ( situation , variableName ) ) {
2017-01-10 18:22:44 +00:00
// Si l'expression n'est pas vraie...
2017-01-17 09:04:34 +00:00
if ( ! evaluation ( situation ) ) {
2017-01-10 18:22:44 +00:00
// On court-circuite toute la variable, et on n'a besoin d'aucune information !
return R . reduced ( [ [ ] ] )
} else {
// Sinon, on continue
return [ variableNames ]
}
// sinon on demande la valeur de cette variable
} else return [ [ ... variableNames , variableName ] ]
}
if ( key === 'non applicable si' ) {
let conditions = value [ 'l\'une de ces conditions' ]
let [ subVariableNames , reduced ] = R . reduce ( ( [ variableNames ] , expression ) => {
let [ variableName , evaluation ] = recognizeExpression ( expression )
2017-01-17 09:04:34 +00:00
if ( knownVariable ( situation , variableName ) ) {
2017-01-10 18:22:44 +00:00
if ( evaluation ( situation ) ) {
return R . reduced ( [ [ ] , true ] )
2017-01-09 17:17:51 +00:00
} else {
2017-01-10 18:22:44 +00:00
return [ variableNames ]
2017-01-09 17:17:51 +00:00
}
}
return [ [ ... variableNames , variableName ] ]
2017-01-10 18:22:44 +00:00
} , [ [ ] , null ] ) ( conditions )
if ( reduced ) return R . reduced ( [ [ ] ] )
else return [ variableNames . concat ( subVariableNames ) ]
}
2017-01-17 09:04:34 +00:00
if ( key === 'formule' ) {
if ( value [ 'linéaire' ] ) {
2017-01-10 18:22:44 +00:00
let { assiette , taux } = value [ 'linéaire' ]
// A propos de l'assiette
let assietteVariableName = removeDiacritics ( assiette ) ,
assietteValue = situation ( assietteVariableName ) ,
unknownAssiette = assietteValue == undefined
2017-01-17 09:04:34 +00:00
if ( unknownAssiette ) {
2017-01-10 18:22:44 +00:00
return [ [ ... variableNames , assietteVariableName ] ]
} else {
if ( variableNames . length > 0 ) {
return [ variableNames ]
2017-01-09 17:17:51 +00:00
}
2017-01-10 18:22:44 +00:00
}
2017-01-09 17:17:51 +00:00
2017-01-10 18:22:44 +00:00
// Arrivés là, cette formule devrait être calculable !
2017-01-09 17:17:51 +00:00
2017-01-10 18:22:44 +00:00
// A propos du taux
2017-01-17 09:04:34 +00:00
if ( typeof taux !== 'string' && typeof taux !== 'number' ) {
2017-01-10 18:22:44 +00:00
throw 'Oups, pas de taux compliqués s\'il-vous-plaît'
}
let tauxValue = taux . indexOf ( '%' ) > - 1 ?
2017-01-17 09:04:34 +00:00
+ taux . replace ( '%' , '' ) / 100 :
2017-01-10 18:22:44 +00:00
+ taux
2017-01-09 17:17:51 +00:00
2017-01-10 18:22:44 +00:00
return R . reduced ( [ null , assietteValue * tauxValue ] )
}
}
2017-01-09 17:17:51 +00:00
2017-01-10 18:22:44 +00:00
return [ variableNames ]
2017-01-17 09:04:34 +00:00
} , [ [ ] , null ] )
2017-01-10 18:22:44 +00:00
)
2017-01-09 17:17:51 +00:00
2017-01-19 15:27:27 +00:00
let analyseRule = situation =>
2017-01-10 18:22:44 +00:00
R . pipe (
extractRuleTypeAndName , // -> {type, name, rule}
data => R . assoc (
'derived' ,
deriveRule ( situation ) ( data . rule )
) ( data )
2017-01-09 17:17:51 +00:00
)
2017-01-10 18:22:44 +00:00
export let analyseSituation = situation =>
2017-01-20 11:08:43 +00:00
selectedRules . map ( analyseRule ( situation ) )
2017-01-10 14:39:40 +00:00
export let variableType = name => {
2017-01-10 18:22:44 +00:00
if ( name == null ) return null
let found = findRuleByName ( name )
2017-01-10 14:39:40 +00:00
// tellement peu de variables pour l'instant
// que c'est très simpliste
2017-01-10 18:22:44 +00:00
if ( ! found ) return 'boolean'
let { rule , type } = found
if ( typeof rule . formule [ 'somme' ] !== 'undefined' ) return 'numeric'
2017-01-10 14:39:40 +00:00
}
2017-01-19 15:27:27 +00:00
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ce qui suit est la première tentative d ' écriture du principe du moteur et de la syntaxe * /
2017-01-09 17:17:51 +00:00
// let types = {
/ *
( expression ) :
| ( variable )
| ( négation )
| ( égalité )
| ( comparaison numérique )
| ( test d ' inclusion court )
* /
// }
// let root = {
// Variable: {
// 'concerne': types['expression'],
// 'ne concerne pas': types['expression']
// // 'applicable si': types['boolean logic'],
// // 'non applicable si': types['boolean logic']
// }
// }
/ *
Variable :
- applicable si : ( boolean logic )
- non applicable si : ( boolean logic )
- concerne : ( expression )
- ne concerne pas : ( expression )
( boolean logic ) :
toutes ces conditions : ( [ expression | boolean logic ] )
l ' une de ces conditions : ( [ expression | boolean logic ] )
conditions exclusives : ( [ expression | boolean logic ] )
"If you write a regular expression, walk away for a cup of coffee, come back, and can't easily understand what you just wrote, then you should look for a clearer way to express what you're doing."
Les expressions sont le seul mécanisme relativement embêtant pour le moteur . Dans un premier temps , il les gerera au moyen d 'expressions régulières, puis il faudra probablement mieux s' équiper avec un "javascript parser generator" :
https : //medium.com/@daffl/beyond-regex-writing-a-parser-in-javascript-8c9ed10576a6
( variable ) : ( string )
( négation ) :
! ( variable )
( égalité ) :
( variable ) = ( variable . type )
( comparaison numérique ) :
| ( variable ) < ( variable . type )
| ( variable ) <= ( variable . type )
| ( variable ) > ( variable . type )
| ( variable ) <= ( variable . type )
( test d ' inclusion court ) :
( variable ) ⊂ [ variable . type ]
in Variable . formule :
- composantes
- linéaire
- barème en taux marginaux
- test d 'inclusion: (test d' inclusion )
( test d ' inclusion ) :
variable : ( variable )
possibilités : [ variable . type ]
# pas nécessaire pour le CDD
in Variable
- variations : [ si ]
( si ) :
si : ( expression )
# corps
* /