Première unité affichée sur la page règle

pull/481/head
Mael 2019-06-11 12:03:45 +02:00
parent 4cab6b464b
commit a7c6cb25fa
14 changed files with 93 additions and 93 deletions

View File

@ -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 : (
<div css="border: 2px dashed chartreuse">
{(formats[valueType !== 'number' ? valueType : unitText] ||
numberFormatter('decimal'))(nodeValue)}
&nbsp;
{unit && unitText}
</div>
)
}

View File

@ -15,7 +15,6 @@ import {
analysisWithDefaultsSelector,
getRuleFromAnalysis
} from 'Selectors/analyseSelectors'
import { humanValue } from 'Engine/rules'
const AnswerList = ({
answers,
@ -57,7 +56,7 @@ const AnswerList = ({
<span
className="answerContent"
style={{ borderBottomColor: colours.textColourOnWhite }}>
{humanValue(answer)(language)}
{answer}
</span>
</button>{' '}
</td>

View File

@ -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 (
<div id="algorithm">
<section id="rule-rules" className={classNames({ showValues })}>

View File

@ -36,7 +36,7 @@ let Namespace = ({ ns, flatRules, colour, sitePaths }) => {
to={
sitePaths.documentation.index + '/' + encodeRuleName(ruleName)
}>
{rule.icon && <span>{emoji(rule.icon)} </span>}
{rule.icons && <span>{emoji(rule.icons)} </span>}
{ruleText}
</Link>
{' '}

View File

@ -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;
}

View File

@ -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(
/>
<section id="rule-content">
{!isNil(displayedRule.nodeValue) && (
<div id="ruleValue">
<span className="ui__ valeur">
{displayedRule.humanValue(
displayedRule.nodeValue,
language
)}
{displayedRule.unit && (
<span>{serializeUnit(displayedRule.unit)}</span>
)}
</span>
</div>
)}
<div id="ruleValue">
<Value {...displayedRule} />
</div>
{displayedRule.defaultValue != null && (
<div id="ruleDefault">
Valeur par défaut :{' '}
{displayedRule.humanValue(
displayedRule.defaultValue,
language
)}
Valeur par défaut : {displayedRule.defaultValue}
</div>
)}
{!valuesToShow && (

View File

@ -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]
}
})

View File

@ -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) => {

View File

@ -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 => {

View File

@ -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) => (
<Node
classes={'inlineExpression ' + k}
@ -185,7 +192,8 @@ let mecanismOperation = (operatorFunction, symbol) => (recurse, k, v) => {
<span className="nodeContent">
<span className="fa fa" />
{makeJsx(explanation[0])}
<span className="operator">{symbol}</span>
<span className="operator">{symbol || k}</span>
{makeJsx(explanation[1])}
</span>
}
@ -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
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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