From a7c6cb25fa8b198b29da6fccba60e7d12bd97fd2 Mon Sep 17 00:00:00 2001 From: Mael Date: Tue, 11 Jun 2019 12:03:45 +0200 Subject: [PATCH] =?UTF-8?q?Premi=C3=A8re=20unit=C3=A9=20affich=C3=A9e=20su?= =?UTF-8?q?r=20la=20page=20r=C3=A8gle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/components/Value.js | 37 ++++++++++++++++++++ source/components/conversation/AnswerList.js | 3 +- source/components/rule/Algorithm.js | 5 ++- source/components/rule/Namespace.js | 2 +- source/components/rule/Rule.css | 2 -- source/components/rule/Rule.js | 25 +++---------- source/engine/grammarFunctions.js | 5 +-- source/engine/rules.js | 30 +++------------- source/engine/traverse.js | 5 +-- source/engine/treat.js | 25 ++++++++----- source/engine/treatVariable.js | 13 +++---- source/engine/units.js | 13 +++---- source/engine/valueFormats.js | 17 ++------- source/règles/base.yaml | 4 +-- 14 files changed, 93 insertions(+), 93 deletions(-) create mode 100644 source/components/Value.js diff --git a/source/components/Value.js b/source/components/Value.js new file mode 100644 index 000000000..81f2991e4 --- /dev/null +++ b/source/components/Value.js @@ -0,0 +1,37 @@ +import React from 'react' +import { memoizeWith } from 'ramda' +import { serialiseUnit } from 'Engine/units' + +const NumberFormat = memoizeWith(JSON.stringify, Intl.NumberFormat) + +let numberFormatter = style => (value, language) => + NumberFormat(language, { + style, + currency: 'EUR', + maximumFractionDigits: 2, + minimumFractionDigits: 2 + }).format(value) + +let booleanTranslations = { + fr: { true: 'Oui', false: 'Non' }, + en: { true: 'Yes', false: 'No' } +} + +let formats = { + '€': numberFormatter('currency'), + boolean: (value, language = 'fr') => booleanTranslations[language][value], + object: value => JSON.stringify(value) +} + +export default ({ nodeValue, unit }) => { + let valueType = typeof nodeValue, + unitText = unit && serialiseUnit(unit) + return nodeValue == undefined ? null : ( +
+ {(formats[valueType !== 'number' ? valueType : unitText] || + numberFormatter('decimal'))(nodeValue)} +   + {unit && unitText} +
+ ) +} diff --git a/source/components/conversation/AnswerList.js b/source/components/conversation/AnswerList.js index 6d7abc1db..777c62e61 100644 --- a/source/components/conversation/AnswerList.js +++ b/source/components/conversation/AnswerList.js @@ -15,7 +15,6 @@ import { analysisWithDefaultsSelector, getRuleFromAnalysis } from 'Selectors/analyseSelectors' -import { humanValue } from 'Engine/rules' const AnswerList = ({ answers, @@ -57,7 +56,7 @@ const AnswerList = ({ - {humanValue(answer)(language)} + {answer} {' '} diff --git a/source/components/rule/Algorithm.js b/source/components/rule/Algorithm.js index c0c6e9d12..b0eb91ffb 100644 --- a/source/components/rule/Algorithm.js +++ b/source/components/rule/Algorithm.js @@ -40,7 +40,10 @@ export default compose(withTranslation())( displayFormula = formula && !!Object.keys(formula).length && - !path(['formule', 'explanation', 'une possibilité'], rule) + !path(['formule', 'explanation', 'une possibilité'], rule) && + formula.explanation?.category !== 'number' + + console.log(formula) return (
diff --git a/source/components/rule/Namespace.js b/source/components/rule/Namespace.js index 6450be0d5..cd8c25353 100644 --- a/source/components/rule/Namespace.js +++ b/source/components/rule/Namespace.js @@ -36,7 +36,7 @@ let Namespace = ({ ns, flatRules, colour, sitePaths }) => { to={ sitePaths.documentation.index + '/' + encodeRuleName(ruleName) }> - {rule.icon && {emoji(rule.icon)} } + {rule.icons && {emoji(rule.icons)} } {ruleText} {' › '} diff --git a/source/components/rule/Rule.css b/source/components/rule/Rule.css index 62f5fecfc..240583ca1 100644 --- a/source/components/rule/Rule.css +++ b/source/components/rule/Rule.css @@ -21,10 +21,8 @@ h2 small { } #rule #ruleValue { - font-weight: 400; text-align: center; font-size: 200%; - color: inherit; margin-bottom: 0.6em; margin-top: 0.4em; } diff --git a/source/components/rule/Rule.js b/source/components/rule/Rule.js index a84461c11..99badb1c6 100644 --- a/source/components/rule/Rule.js +++ b/source/components/rule/Rule.js @@ -29,7 +29,7 @@ import Examples from './Examples' import RuleHeader from './Header' import References from './References' import './Rule.css' -import { serializeUnit } from 'Engine/units' +import Value from 'Components/Value' let LazySource = React.lazy(() => import('./RuleSource')) @@ -64,7 +64,6 @@ export default compose( namespaceRules = findRuleByNamespace(flatRules, dottedName) let displayedRule = analysedExample || analysedRule - debugger return ( <> {this.state.viewSource ? ( @@ -102,26 +101,12 @@ export default compose( />
- {!isNil(displayedRule.nodeValue) && ( -
- - {displayedRule.humanValue( - displayedRule.nodeValue, - language - )} - {displayedRule.unit && ( - {serializeUnit(displayedRule.unit)} - )} - -
- )} +
+ +
{displayedRule.defaultValue != null && (
- Valeur par défaut :{' '} - {displayedRule.humanValue( - displayedRule.defaultValue, - language - )} + Valeur par défaut : {displayedRule.defaultValue}
)} {!valuesToShow && ( diff --git a/source/engine/grammarFunctions.js b/source/engine/grammarFunctions.js index b54683abc..6f4b0c4ff 100644 --- a/source/engine/grammarFunctions.js +++ b/source/engine/grammarFunctions.js @@ -1,13 +1,10 @@ /* Those are postprocessor functions for the Nearley grammar.ne. The advantage of putting them here is to get prettier's JS formatting, since Nealrey doesn't support it https://github.com/kach/nearley/issues/310 */ -import { inferUnit } from 'Engine/units' - export let operation = operationType => ([A, , operator, , B]) => ({ [operator]: { operationType, - explanation: [A, B], - unit: inferUnit(operator, A.unit, B.unit) + explanation: [A, B] } }) diff --git a/source/engine/rules.js b/source/engine/rules.js index e02fb6f4a..52c3370bb 100644 --- a/source/engine/rules.js +++ b/source/engine/rules.js @@ -1,5 +1,3 @@ -// Séparation artificielle, temporaire, entre ces deux types de règles -import valueFormats from 'Engine/valueFormats' import { assoc, chain, @@ -26,7 +24,8 @@ import { take, toPairs, trim, - when + when, + groupBy } from 'ramda' import rawRules from 'Règles/base.yaml' import translations from 'Règles/externalized.yaml' @@ -41,12 +40,7 @@ Functions working on one rule */ export let enrichRule = rule => { try { - let formatKey = rule['format'] || 'booléen', - format = valueFormats[formatKey] - if (!format) { - console.log(`The '${format}' rule format is unknown`) - throw new Error(format) - } + let unit = rule.unité && parseUnit(rule.unité) return { ...rule, type: possibleVariableTypes.find(t => has(t, rule) || rule.type === t), @@ -59,9 +53,7 @@ export let enrichRule = rule => { examples: rule['exemples'], icons: rule['icônes'], summary: rule['résumé'], - format, - humanValue: format.human, - ...(rule.unité ? { unit: parseUnit(rule.unité) } : {}) + unit } } catch (e) { console.log(e) @@ -197,19 +189,6 @@ export let nestedSituationToPathMap = situation => { return fromPairs(rec(situation, [])) } -export let formatInputs = (flatRules, pathValueMap) => - mapObjIndexed((value, path) => { - // Our situationGate retrieves data from the "conversation" form - // The search below is to apply input conversions such as replacing "," with "." - if (name.startsWith('sys.')) return null - - let rule = findRuleByDottedName(flatRules, path), - format = rule ? valueFormats[rule.format] : null, - pre = format && format.validator.pre ? format.validator.pre : identity - - return pre(value) - }, pathValueMap) - /* Traduction */ export let translateAll = (translations, flatRules) => { @@ -255,6 +234,7 @@ export let translateAll = (translations, flatRules) => { export let rules = translateAll(translations, rawRules).map(rule => enrichRule(rule) ) + export let rulesFr = rawRules.map(rule => enrichRule(rule)) export let findParentDependency = (rules, rule) => { diff --git a/source/engine/traverse.js b/source/engine/traverse.js index 7d8c09106..4ac838ccb 100644 --- a/source/engine/traverse.js +++ b/source/engine/traverse.js @@ -267,7 +267,7 @@ export let treatRuleRoot = (rules, rule) => { ...parsedRoot, evaluate, parsed: true, - unit: root.formule?.explanation?.unit + unit: root.unit || parsedRoot.formule?.explanation?.unit } } @@ -327,7 +327,8 @@ export let getTargets = (target, rules) => { export let parseAll = flatRules => { let treatOne = rule => treatRuleRoot(flatRules, rule) - return map(treatOne, flatRules) + let parsed = map(treatOne, flatRules) + return parsed } export let analyseMany = (parsedRules, targetNames) => situationGate => { diff --git a/source/engine/treat.js b/source/engine/treat.js index ab40877f7..9182de282 100644 --- a/source/engine/treat.js +++ b/source/engine/treat.js @@ -18,7 +18,8 @@ import { map, multiply, propOr, - subtract + subtract, + fromPairs } from 'ramda' import React from 'react' import { evaluateNode, makeJsx, mergeMissing, rewriteNode } from './evaluation' @@ -49,6 +50,8 @@ import { treatVariableTransforms } from './treatVariable' +import { inferUnit } from 'Engine/units' + export let nearley = () => new Parser(Grammar.ParserRules, Grammar.ParserStart) export let treatString = (rules, rule) => rawNode => { @@ -107,9 +110,11 @@ export let treatObject = (rules, rule, treatOptions) => rawNode => { '=': [equals], '!=': [(a, b) => !equals(a, b), '≠'] }, - operationDispatch = map( - ([f, symbol]) => mecanismOperation(f, symbol || k), - knownOperations + operationDispatch = fromPairs( + Object.entries(knownOperations).map(([k, [f, symbol]]) => [ + k, + mecanismOperation(k, f, symbol) + ]) ) let dispatch = { @@ -155,7 +160,7 @@ export let treatObject = (rules, rule, treatOptions) => rawNode => { return action(treat(rules, rule, treatOptions), k, v) } -let mecanismOperation = (operatorFunction, symbol) => (recurse, k, v) => { +let mecanismOperation = (k, operatorFunction, symbol) => (recurse, k, v) => { let evaluate = (cache, situation, parsedRules, node) => { let explanation = map( curry(evaluateNode)(cache, situation, parsedRules), @@ -177,6 +182,8 @@ let mecanismOperation = (operatorFunction, symbol) => (recurse, k, v) => { let explanation = v.explanation.map(recurse) + let unit = inferUnit(k, explanation[0].unit, explanation[1].unit) + let jsx = (nodeValue, explanation) => ( (recurse, k, v) => { {makeJsx(explanation[0])} - {symbol} + {symbol || k} + {makeJsx(explanation[1])} } @@ -196,8 +204,9 @@ let mecanismOperation = (operatorFunction, symbol) => (recurse, k, v) => { ...v, evaluate, jsx, - operator: symbol, + operator: symbol || k, // is this useful ? text: rawNode, - explanation + explanation, + unit } } diff --git a/source/engine/treatVariable.js b/source/engine/treatVariable.js index 479ab9fb4..d92bdfa36 100644 --- a/source/engine/treatVariable.js +++ b/source/engine/treatVariable.js @@ -10,6 +10,10 @@ import { import { getSituationValue } from './variables' export let treatVariable = (rules, rule, filter) => ({ fragments }) => { + let variablePartialName = fragments.join(' . '), + dottedName = disambiguateRuleReference(rules, rule, variablePartialName), + variable = findRuleByDottedName(rules, dottedName) + let evaluate = (cache, situation, parsedRules, node) => { let dottedName = node.dottedName, // On va vérifier dans le cache courant, dict, si la variable n'a pas été déjà évaluée @@ -18,8 +22,7 @@ export let treatVariable = (rules, rule, filter) => ({ fragments }) => { cached = cache[cacheName] if (cached) return cached - let variable = findRuleByDottedName(parsedRules, dottedName), - variableHasFormula = variable.formule != null, + let variableHasFormula = variable.formule != null, variableHasCond = variable['applicable si'] != null || variable['non applicable si'] != null || @@ -72,9 +75,6 @@ export let treatVariable = (rules, rule, filter) => ({ fragments }) => { } } - let variablePartialName = fragments.join(' . '), - dottedName = disambiguateRuleReference(rules, rule, variablePartialName) - return { evaluate, //eslint-disable-next-line react/display-name @@ -91,7 +91,8 @@ export let treatVariable = (rules, rule, filter) => ({ fragments }) => { name: variablePartialName, category: 'variable', fragments, - dottedName + dottedName, + unit: variable.unit } } diff --git a/source/engine/units.js b/source/engine/units.js index 38d229f70..fd7783f5b 100644 --- a/source/engine/units.js +++ b/source/engine/units.js @@ -1,14 +1,15 @@ import { remove, isEmpty } from 'ramda' export let parseUnit = string => { - let [a, b = ''] = string.split('/') - return { - numerators: a !== '' ? [a] : [], - denominators: b !== '' ? [b] : [] - } + let [a, b = ''] = string.split('/'), + result = { + numerators: a !== '' ? [a] : [], + denominators: b !== '' ? [b] : [] + } + return result } -export let serializeUnit = ({ numerators, denominators }) => { +export let serialiseUnit = ({ numerators, denominators }) => { let n = !isEmpty(numerators) let d = !isEmpty(denominators) return n && !d diff --git a/source/engine/valueFormats.js b/source/engine/valueFormats.js index 6ce6e60e9..62d39b7be 100644 --- a/source/engine/valueFormats.js +++ b/source/engine/valueFormats.js @@ -1,18 +1,7 @@ import { number, int } from './validators' -import { memoizeWith } from 'ramda' - -const NumberFormat = memoizeWith(JSON.stringify, Intl.NumberFormat) - -let numberFormatter = style => (value, language) => - NumberFormat(language, { - style, - currency: 'EUR', - maximumFractionDigits: 2, - minimumFractionDigits: 2 - }).format(value) let pourcentage = { - human: numberFormatter('decimal'), + human: () => null, validator: number } @@ -27,12 +16,12 @@ let jours = { } let nombre = { - human: numberFormatter('decimal'), + human: () => null, validator: int } let euros = { - human: numberFormatter('currency'), + human: () => null, validator: number } diff --git a/source/règles/base.yaml b/source/règles/base.yaml index b3e0f6d4f..1cb9b808d 100644 --- a/source/règles/base.yaml +++ b/source/règles/base.yaml @@ -43,11 +43,11 @@ nom: distance journalière description: Une estimation basse de la distance parcourue à vélo par un salarié pour se rendre à son travail. formule: 4 - unité: km + unité: km/jour - espace: contrat salarié . indemnité kilométrique vélo nom: jours travaillés formule: 218 - unité: jours + unité: jour - espace: contrat salarié . indemnité kilométrique vélo nom: active