From 151c83b4793c9a130b6af428016f692713646362 Mon Sep 17 00:00:00 2001 From: Mael Thomas Date: Thu, 19 Jan 2017 16:27:27 +0100 Subject: [PATCH] =?UTF-8?q?[moteur]=20les=20fichiers=20sont=20r=C3=A9ordon?= =?UTF-8?q?n=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- règles/Entités/Salariat.CDD.yaml | 10 +- règles/rémunération-travail/cdd/CIF.yaml | 6 +- .../cdd/indemnité_fin_contrat.yaml | 16 +-- .../cdd/majoration-chomage.yaml | 6 +- source/engine/explication-demo-CDD.md | 22 ++++ source/engine/expressions.js | 48 ++++++++ source/{ => engine}/load-rules.js | 0 source/{utils => engine}/remove-diacritics.js | 0 source/{model.js => engine/rules.js} | 0 source/{ => engine}/traverse.js | 104 ++++-------------- source/initialSituation.js | 19 ---- 11 files changed, 110 insertions(+), 121 deletions(-) create mode 100644 source/engine/explication-demo-CDD.md create mode 100644 source/engine/expressions.js rename source/{ => engine}/load-rules.js (100%) rename source/{utils => engine}/remove-diacritics.js (100%) rename source/{model.js => engine/rules.js} (100%) rename source/{ => engine}/traverse.js (58%) delete mode 100644 source/initialSituation.js diff --git a/règles/Entités/Salariat.CDD.yaml b/règles/Entités/Salariat.CDD.yaml index 96de928d5..03a4f5e5a 100644 --- a/règles/Entités/Salariat.CDD.yaml +++ b/règles/Entités/Salariat.CDD.yaml @@ -56,13 +56,13 @@ - Variable: CDD poursuivi en CDI - attache: Salariat . CDD . évènements + attache: Salariat . CDD . événements possibilités exclusives: - embauche en CDI suivant le CDD - CDD requalifié en CDI # quand ça arrive ? - Variable: refus CDI avantageux - attache: Salariat . CDD . évènements + attache: Salariat . CDD . événements #TODO qu'est-ce ? (emploi similaire, rémunération >=) @@ -70,11 +70,11 @@ attache: Salariat . CDD description: L'employeur s'engage à fournir une formation professionnelle, ce qui le dispense de la cotisation CIF CDD -- Variable: rupture anticipée salarié +- Variable: anticipée salarié attache: Salariat . CDD . ruptures -- Variable: rupture pour faute grave, lourde, cas de force majeure +- Variable: pour faute grave, lourde, cas de force majeure attache: Salariat . CDD . ruptures -- Variable: rupture CDD pendant période essai +- Variable: pendant période essai attache: Salariat . CDD . ruptures diff --git a/règles/rémunération-travail/cdd/CIF.yaml b/règles/rémunération-travail/cdd/CIF.yaml index 38e02dd53..9d749490b 100644 --- a/règles/rémunération-travail/cdd/CIF.yaml +++ b/règles/rémunération-travail/cdd/CIF.yaml @@ -6,12 +6,12 @@ référence: Code du travail - Article L6322-37 non applicable si: l'une de ces conditions: - - CDD poursuivi en CDI + - CDD . événements . CDD poursuivi en CDI - CDD . type = saisonnier - CDD . type = jeune vacances - - contrat aidé + - Salariat . contrat aidé formule: linéaire: - assiette: assiette cotisations sociales + assiette: Salariat . salaire de base taux: 1% diff --git a/règles/rémunération-travail/cdd/indemnité_fin_contrat.yaml b/règles/rémunération-travail/cdd/indemnité_fin_contrat.yaml index 7306bbb29..69efb7e57 100644 --- a/règles/rémunération-travail/cdd/indemnité_fin_contrat.yaml +++ b/règles/rémunération-travail/cdd/indemnité_fin_contrat.yaml @@ -9,25 +9,25 @@ non applicable si: l'une de ces conditions: # Evènements particuliers - - CDD poursuivi en CDI - - refus CDI avantageux + - CDD . événements . CDD poursuivi en CDI + - CDD . événements . refus CDI avantageux # Rupture - - rupture anticipée salarié - - rupture pour faute grave, lourde, cas de force majeure - - rupture CDD pendant période essai + - CDD . rupture . anticipée salarié + - CDD . rupture . pour faute grave, lourde, cas de force majeure + - CDD . rupture . pendant période essai - - complément formation professionnelle employeur + - CDD . complément formation professionnelle employeur # types de contrat - - contrat aidé + - Salariat . contrat aidé - CDD . type = usage - CDD . type = contrat jeune vacances - CDD . type = saisonnier formule: linéaire: - assiette: assiette cotisations sociales + assiette: Salariat . salaire de base taux: 10% diff --git a/règles/rémunération-travail/cdd/majoration-chomage.yaml b/règles/rémunération-travail/cdd/majoration-chomage.yaml index 1a7a580f5..0d472b43b 100644 --- a/règles/rémunération-travail/cdd/majoration-chomage.yaml +++ b/règles/rémunération-travail/cdd/majoration-chomage.yaml @@ -13,10 +13,10 @@ logique numérique: - CDD poursuivi en CDI: 0% - Contrat . type = accroissement temporaire d'activité: - - CDD . durée ≤ 1 mois: 3% - - contrat de travail durée ≤ 3 mois: 1.5% + - CDD . durée ≤ 1: 3% # TODO 1 mois, pas 1 rien, évidemment + - contrat de travail durée ≤ 3: 1.5% - Contrat . type = usage: - - CDD . durée ≤ 3 mois: 0.5% + - CDD . durée ≤ 3: 0.5% diff --git a/source/engine/explication-demo-CDD.md b/source/engine/explication-demo-CDD.md new file mode 100644 index 000000000..9c08f6369 --- /dev/null +++ b/source/engine/explication-demo-CDD.md @@ -0,0 +1,22 @@ +L'objectif dans un premier temps est de faire une démonstration d'interface de saisie pour calculer les obligations du CDD. Le CDD est un contrat d'exception, ce qui le rend assez complexe. + +Les Variables du système social comportent des entrées particulières (des cléfs de l'objet) que l'on nommera "mécanismes". Elles diffèrent des entrées simples (telle la description d'une variable) car elles sont susceptibles de comporter des variables, et la description de calculs. + +Voici une liste des mécanismes qui sont à traverser pour notamment : + - d'extraire les variables utilisées et donc que l'utilisateur devra saisir + - d'attribuer une note à ces variables pour déterminer la prochaine saisie (ou "question") + - de court-circuiter les branches rendues inutiles par la situation courante saisie par l'utilisateur, ce qui influence la note. + +Dans un premier temps, l'idée est de créer un formulaire à questions unitaires optimisées pour que la saisie de données inutiles soit évitée. + +- Il faut résoudre le calcul des variables. + - ça introduit l'assiette 2300€ + - ça nous donne son intervalle en % vu que l'assiette est constante, et donc un avancement du formulaire + - ça nous donne des résultats !!!!!! :)) + +- Il faut donner des explications à TOUTES les variables. Aucune n'est triviale ! + +- Il faut ajouter la notion d'entité. +- Ce qui permettra de regrouper les questions par thème. Exemple, demander "Quel type de CDD" et ordonner les réponses possibles par influence (e.g. si c'est un CDD d'usage ) + +----------------------------------------- diff --git a/source/engine/expressions.js b/source/engine/expressions.js new file mode 100644 index 000000000..72786a3cc --- /dev/null +++ b/source/engine/expressions.js @@ -0,0 +1,48 @@ +import removeDiacritics from './remove-diacritics' + +// TODO: handle dotted variable syntax +// ([\w\s]+(\s\.?\s\w+)+)\s([?]?=?)\s([\w\s]+) +var replace = "regex"; +var re = new RegExp(replace,"g"); +"mystring".replace(re, "newstring"); + +// Ces regexp sont trop complexe. Ce n'est que temporaire ! + +let expressionTests = { + // 'negatedVariable': v => /!((?:[a-z0-9]|\s|_)+)/g.exec(v), + // 'variableIsIncludedIn': v => /((?:[a-z0-9]|\s|_)+)⊂*/g.exec(v), + 'variableComparedToNumber': v => /([\w\s]+(?:\s\.\s[\w\s]+)*)\s([<>]=?)\s([0-9]+)/g.exec(v), + 'variableEqualsString': v => /([\w\s]+(?:\s\.\s[\w\s]+)*)\s=\s([\w\s]+)/g.exec(v), + 'variable': v => /^([\w\s]+(?:\s\.\s[\w\s]+)*)$/g.exec(v) +} + +export let recognizeExpression = rawValue => { + let + value = removeDiacritics(rawValue).toLowerCase(), + match + + // match = expressionTests['negatedVariable'](value) + // if (match) { + // let [, variableName] = match + // // return [variableName, `!${variableName}`] + // return [variableName, situation => situation(variableName) == 'non'] + // } + + match = expressionTests['variableComparedToNumber'](value) + if (match) { + let [, variableName, symbol, number] = match + return [variableName, situation => eval(`situation("${variableName}") ${symbol} ${number}`)] // eslint-disable-line no-unused-vars + } + + match = expressionTests['variableEqualsString'](value) + if (match) { + let [, variableName, string] = match + return [variableName, situation => situation(variableName) == number] + } + + match = expressionTests['variable'](value) + if (match) { + let [variableName] = match + return [variableName, situation => situation(variableName) == 'oui'] + } +} diff --git a/source/load-rules.js b/source/engine/load-rules.js similarity index 100% rename from source/load-rules.js rename to source/engine/load-rules.js diff --git a/source/utils/remove-diacritics.js b/source/engine/remove-diacritics.js similarity index 100% rename from source/utils/remove-diacritics.js rename to source/engine/remove-diacritics.js diff --git a/source/model.js b/source/engine/rules.js similarity index 100% rename from source/model.js rename to source/engine/rules.js diff --git a/source/traverse.js b/source/engine/traverse.js similarity index 58% rename from source/traverse.js rename to source/engine/traverse.js index 5cc702b98..e057dffc2 100644 --- a/source/traverse.js +++ b/source/engine/traverse.js @@ -1,82 +1,18 @@ -import removeDiacritics from './utils/remove-diacritics' import R from 'ramda' import rules from './load-rules' -// import initialSituation from './initialSituation' -import {findRuleByName, extractRuleTypeAndName} from './model' +import removeDiacritics from './remove-diacritics' +import {findRuleByName, extractRuleTypeAndName} from './rules' +import {recognizeExpression} from './recognizeExpression' -/* -L'objectif dans un premier temps est de faire une démonstration d'interface de saisie pour calculer les obligations du CDD. Le CDD est un contrat d'exception, ce qui le rend assez complexe. +// 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'] + ) + ) -Les Variables du système social comportent des entrées particulières (des cléfs de l'objet) que l'on nommera "mécanismes". Elles diffèrent des entrées simples (telle la description d'une variable) car elles sont susceptibles de comporter des variables, et la description de calculs. - -Voici une liste des mécanismes qui sont à traverser pour notamment : - - d'extraire les variables utilisées et donc que l'utilisateur devra saisir - - d'attribuer une note à ces variables pour déterminer la prochaine saisie (ou "question") - - de court-circuiter les branches rendues inutiles par la situation courante saisie par l'utilisateur, ce qui influence la note. - -Dans un premier temps, l'idée est de créer un formulaire à questions unitaires optimisées pour que la saisie de données inutiles soit évitée. - -- Il faut résoudre le calcul des variables. - - ça introduit l'assiette 2300€ - - ça nous donne son intervalle en % vu que l'assiette est constante, et donc un avancement du formulaire - - ça nous donne des résultats !!!!!! :)) - -- Il faut donner des explications à TOUTES les variables. Aucune n'est triviale ! - -- Il faut ajouter la notion d'entité. -- Ce qui permettra de regrouper les questions par thème. Exemple, demander "Quel type de CDD" et ordonner les réponses possibles par influence (e.g. si c'est un CDD d'usage ) - ------------------------------------------ - -*/ - -let expressionTests = { - 'negatedVariable': v => /!((?:[a-z0-9]|\s|_)+)/g.exec(v), - // Cette regexp est trop complexe (il faut parser le tableau après le symbole d'inclusion) ! - // 'variableIsIncludedIn': v => /((?:[a-z0-9]|\s|_)+)⊂*/g.exec(v), - 'variableComparedToNumber': v => /((?:[a-z0-9]|\s|_)+)([<|>]=?)\s+([0-9]+)/g.exec(v), - 'numberComparedToVariable': v => /([0-9]+)\s+([<|>]=?)((?:[a-z0-9]|\s|_)+)/g.exec(v), - 'variableEqualsNumber': v => /((?:[a-z0-9]|\s|_)+)=((?:[a-z0-9]|\s|_)+)/g.exec(v), - 'variable': v => /((?:[a-z0-9]|\s|_)+)/g.exec(v) -} - -let recognizeExpression = rawValue => { - let - value = removeDiacritics(rawValue).toLowerCase(), - match - - match = expressionTests['negatedVariable'](value) - if (match) { - let [, variableName] = match - // return [variableName, `!${variableName}`] - return [variableName, situation => situation(variableName) == 'non'] - } - - match = expressionTests['variableComparedToNumber'](value) - if (match) { - let [, variableName, symbol, number] = match - return [variableName, situation => eval(`situation("${variableName}") ${symbol} ${number}`)] // eslint-disable-line no-unused-vars - } - - match = expressionTests['numberComparedToVariable'](value) - if (match) { - let [, number, symbol, variableName] = match - return [variableName, situation => eval(`${number} ${symbol} situation("${variableName}")`)] // eslint-disable-line no-unused-vars - } - - match = expressionTests['variableEqualsNumber'](value) - if (match) { - let [, variableName, number] = match - return [variableName, situation => situation(variableName) == number] - } - - match = expressionTests['variable'](value) - if (match) { - let [variableName] = match - return [variableName, situation => situation(variableName) == 'oui'] - } -} let knownVariable = (situation, variableName) => (typeof situation(variableName) !== 'undefined') @@ -153,7 +89,7 @@ let deriveRule = situation => R.pipe( }, [[], null]) ) -let analyseVariable = situation => +let analyseRule = situation => R.pipe( extractRuleTypeAndName, // -> {type, name, rule} data => R.assoc( @@ -162,17 +98,10 @@ let analyseVariable = situation => )(data) ) -// 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'] - ) - ) export let analyseSituation = situation => R.pipe( - R.map(analyseVariable(situation)) + R.map(analyseRule(situation)) )(selectedRules) export let variableType = name => { @@ -187,6 +116,15 @@ export let variableType = name => { if (typeof rule.formule['somme'] !== 'undefined') return 'numeric' } + + + + + + +/*-------------------------------------------------------------------------------- + Ce qui suit est la première tentative d'écriture du principe du moteur et de la syntaxe */ + // let types = { /* (expression): diff --git a/source/initialSituation.js b/source/initialSituation.js deleted file mode 100644 index 0426f2777..000000000 --- a/source/initialSituation.js +++ /dev/null @@ -1,19 +0,0 @@ -import R from 'ramda' -import removeDiacritics from './utils/remove-diacritics' - -let initialSituation = R.pipe( - R.toPairs, - R.map(([k,v])=>[removeDiacritics(k).toLowerCase(), v]), - R.fromPairs -)({ - 'durée determinée': true, - // 'refus CDI avantageux': true - 'CDD poursuivi en CDI': false, - 'CDD type saisonnier': false, - // 'contrat jeune vacances': false, - 'contrat aidé': false, - 'apprentissage': false, - 'assiette cotisations sociales': 2300 -}) - -export default initialSituation