Merge pull request #719 from betagouv/dottedname
Utilisation de la notation pointée pour définir les règlespull/738/head
commit
f72ab75fb2
|
@ -10,7 +10,7 @@ import { Router } from 'react-router-dom'
|
|||
import reducers from 'Reducers/rootReducer'
|
||||
import { applyMiddleware, compose, createStore } from 'redux'
|
||||
import thunk from 'redux-thunk'
|
||||
import { getIframeOption, inIframe } from './utils'
|
||||
import { inIframe } from './utils'
|
||||
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
|
||||
|
||||
|
@ -73,10 +73,13 @@ export default class Provider extends PureComponent {
|
|||
this.props.tracker.disconnectFromHistory()
|
||||
}
|
||||
render() {
|
||||
const iframeCouleur = new URLSearchParams(
|
||||
document.location.search.substring(1)
|
||||
).get('couleur')
|
||||
return (
|
||||
// If IE < 11 display nothing
|
||||
<ReduxProvider store={this.store}>
|
||||
<ThemeColoursProvider colour={getIframeOption('couleur')}>
|
||||
<ThemeColoursProvider colour={iframeCouleur}>
|
||||
<TrackerProvider value={this.props.tracker}>
|
||||
<SitePathProvider value={this.props.sitePaths}>
|
||||
<I18nextProvider i18n={i18next}>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { React, T } from 'Components'
|
||||
import { serialiseUnit } from 'Engine/units'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatValue } from 'Engine/format'
|
||||
|
||||
|
@ -42,8 +41,6 @@ export default function Value({
|
|||
</span>
|
||||
)
|
||||
let valueType = typeof nodeValue,
|
||||
unitText =
|
||||
unit !== null && (typeof unit == 'object' ? serialiseUnit(unit) : unit),
|
||||
formattedValue =
|
||||
valueType === 'string' ? (
|
||||
<T>{nodeValue}</T>
|
||||
|
@ -56,8 +53,8 @@ export default function Value({
|
|||
minimumFractionDigits,
|
||||
maximumFractionDigits,
|
||||
language,
|
||||
value: nodeValue,
|
||||
unit: unitText
|
||||
unit,
|
||||
value: nodeValue
|
||||
})
|
||||
)
|
||||
|
||||
|
|
|
@ -1,39 +1,44 @@
|
|||
import { toPairs } from 'ramda'
|
||||
import React from 'react'
|
||||
import { capitalise0 } from '../../utils'
|
||||
import references from 'Règles/ressources/références/références.yaml'
|
||||
import './References.css'
|
||||
|
||||
export default function References({ refs }) {
|
||||
const renderRef = ([name, link]) => {
|
||||
let refKey = findRefKey(link),
|
||||
refData = (refKey && references[refKey]) || {},
|
||||
domain = cleanDomain(link)
|
||||
const findRefKey = link =>
|
||||
Object.keys(references).find(r => link.indexOf(r) > -1)
|
||||
|
||||
return (
|
||||
<li key={name}>
|
||||
<span className="imageWrapper">
|
||||
{refData.image && (
|
||||
<img
|
||||
src={require('Règles/ressources/références/' + refData.image)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
<a href={link} target="_blank">
|
||||
{capitalise0(name)}
|
||||
</a>
|
||||
<span className="url">{domain}</span>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
const findRefKey = link =>
|
||||
Object.keys(references).find(r => link.indexOf(r) > -1)
|
||||
const cleanDomain = link =>
|
||||
(link.indexOf('://') > -1 ? link.split('/')[2] : link.split('/')[0]).replace(
|
||||
'www.',
|
||||
''
|
||||
)
|
||||
|
||||
const cleanDomain = link =>
|
||||
(link.indexOf('://') > -1
|
||||
? link.split('/')[2]
|
||||
: link.split('/')[0]
|
||||
).replace('www.', '')
|
||||
|
||||
let references = toPairs(refs)
|
||||
return <ul className="references">{references.map(renderRef)}</ul>
|
||||
function Ref({ name, link }) {
|
||||
let refKey = findRefKey(link),
|
||||
refData = (refKey && references[refKey]) || {},
|
||||
domain = cleanDomain(link)
|
||||
return (
|
||||
<li key={name}>
|
||||
<span className="imageWrapper">
|
||||
{refData.image && (
|
||||
<img src={require('Règles/ressources/références/' + refData.image)} />
|
||||
)}
|
||||
</span>
|
||||
<a href={link} target="_blank">
|
||||
{capitalise0(name)}
|
||||
</a>
|
||||
<span className="url">{domain}</span>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default function References({ refs }) {
|
||||
let references = toPairs(refs)
|
||||
return (
|
||||
<ul className="references">
|
||||
{references.map(([name, link]) => (
|
||||
<Ref key={link} name={name} link={link} />
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { buildDottedName } from 'Engine/rules'
|
||||
import { safeDump } from 'js-yaml'
|
||||
import React from 'react'
|
||||
import emoji from 'react-easy-emoji'
|
||||
|
@ -6,7 +5,7 @@ import rules from 'Règles/base.yaml'
|
|||
import ColoredYaml from './ColoredYaml'
|
||||
|
||||
export default function RuleSource({ dottedName }) {
|
||||
let source = rules.filter(rule => buildDottedName(rule).includes(dottedName))
|
||||
let source = rules[dottedName]
|
||||
|
||||
return (
|
||||
<div id="RuleSource" className="ui__ container">
|
||||
|
|
|
@ -58,7 +58,7 @@ export function formatValue({
|
|||
if (typeof value !== 'number') {
|
||||
return value
|
||||
}
|
||||
const serializedUnit = typeof unit == 'object' ? serialiseUnit(unit) : unit
|
||||
const serializedUnit = serialiseUnit(unit, value)
|
||||
|
||||
switch (serializedUnit) {
|
||||
case '€':
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from 'ramda'
|
||||
import React from 'react'
|
||||
import { findRuleByDottedName, queryRule } from './rules'
|
||||
import {serialiseUnit} from 'Engine/units'
|
||||
import { serialiseUnit } from 'Engine/units'
|
||||
|
||||
/*
|
||||
COLLECTE DES VARIABLES MANQUANTES
|
||||
|
|
|
@ -10,8 +10,16 @@ let inputToStateSelector = rules => input => dottedName =>
|
|||
...input
|
||||
}[dottedName])
|
||||
|
||||
let enrichRules = input =>
|
||||
(typeof input === 'string' ? safeLoad(input) : input).map(enrichRule)
|
||||
let enrichRules = input => {
|
||||
const rules = typeof input === 'string' ? safeLoad(input) : input
|
||||
const rulesList = Array.isArray(rules)
|
||||
? rules
|
||||
: Object.entries(rules).map(([dottedName, rule]) => ({
|
||||
dottedName,
|
||||
...rule
|
||||
}))
|
||||
return rulesList.map(enrichRule)
|
||||
}
|
||||
|
||||
export default {
|
||||
evaluate: (targetInput, input, config) => {
|
||||
|
|
|
@ -37,13 +37,14 @@ Functions working on one rule */
|
|||
export let enrichRule = rule => {
|
||||
try {
|
||||
let unit = rule.unité && parseUnit(rule.unité)
|
||||
const dottedName = rule.dottedName || rule.nom
|
||||
const name = nameLeaf(dottedName)
|
||||
return {
|
||||
...rule,
|
||||
dottedName,
|
||||
name,
|
||||
type: possibleVariableTypes.find(t => has(t, rule) || rule.type === t),
|
||||
name: rule['nom'],
|
||||
title: capitalise0(rule['titre'] || rule['nom']),
|
||||
ns: rule['espace'],
|
||||
dottedName: buildDottedName(rule),
|
||||
title: capitalise0(rule['titre'] || name),
|
||||
defaultValue: rule['par défaut'],
|
||||
examples: rule['exemples'],
|
||||
icons: rule['icônes'],
|
||||
|
@ -56,9 +57,6 @@ export let enrichRule = rule => {
|
|||
}
|
||||
}
|
||||
|
||||
export let buildDottedName = rule =>
|
||||
rule['espace'] ? [rule['espace'], rule['nom']].join(' . ') : rule['nom']
|
||||
|
||||
// les variables dans les tests peuvent être exprimées relativement à l'espace de nom de la règle,
|
||||
// comme dans sa formule
|
||||
export let disambiguateExampleSituation = (rules, rule) =>
|
||||
|
@ -166,7 +164,7 @@ export let findRule = (rules, nameOrDottedName) =>
|
|||
: findRuleByName(rules, nameOrDottedName)
|
||||
|
||||
export let findRuleByNamespace = (allRules, ns) =>
|
||||
allRules.filter(propEq('ns', ns))
|
||||
allRules.filter(rule => parentName(rule.dottedName) === ns)
|
||||
|
||||
/*********************************
|
||||
Autres */
|
||||
|
@ -186,7 +184,7 @@ export let nestedSituationToPathMap = situation => {
|
|||
/* Traduction */
|
||||
|
||||
export let translateAll = (translations, flatRules) => {
|
||||
let translationsOf = rule => translations[buildDottedName(rule)],
|
||||
let translationsOf = rule => translations[rule.dottedName],
|
||||
translateProp = (lang, translation) => (rule, prop) => {
|
||||
let propTrans = translation[prop + '.' + lang]
|
||||
if (prop === 'suggestions' && propTrans)
|
||||
|
@ -223,12 +221,17 @@ export let translateAll = (translations, flatRules) => {
|
|||
return map(translateRule('en', translations, targets), flatRules)
|
||||
}
|
||||
|
||||
const rulesList = Object.entries(rawRules).map(([dottedName, rule]) => ({
|
||||
dottedName,
|
||||
...rule
|
||||
}))
|
||||
|
||||
// On enrichit la base de règles avec des propriétés dérivées de celles du YAML
|
||||
export let rules = translateAll(translations, rawRules).map(rule =>
|
||||
export let rules = translateAll(translations, rulesList).map(rule =>
|
||||
enrichRule(rule)
|
||||
)
|
||||
|
||||
export let rulesFr = rawRules.map(rule => enrichRule(rule))
|
||||
export let rulesFr = rulesList.map(rule => enrichRule(rule))
|
||||
|
||||
export let findParentDependency = (rules, rule) => {
|
||||
// A parent dependency means that one of a rule's parents is not just a namespace holder, it is a boolean question. E.g. is it a fixed-term contract, yes / no
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { remove, isEmpty, unnest } from 'ramda'
|
||||
import i18n from '../i18n'
|
||||
|
||||
//TODO this function does not handle complex units like passenger-kilometer/flight
|
||||
export let parseUnit = string => {
|
||||
|
@ -10,12 +11,21 @@ export let parseUnit = string => {
|
|||
return result
|
||||
}
|
||||
|
||||
let printUnits = units => units.filter(unit => unit !== '%').join('-')
|
||||
let printUnits = (units, count) =>
|
||||
units
|
||||
.filter(unit => unit !== '%')
|
||||
.map(unit => i18n.t(`units:${unit}`, { count }))
|
||||
.join('-')
|
||||
|
||||
export let serialiseUnit = rawUnit => {
|
||||
const plural = 2
|
||||
export let serialiseUnit = (rawUnit, count = plural) => {
|
||||
if (typeof rawUnit !== 'object') {
|
||||
return typeof rawUnit === 'string'
|
||||
? i18n.t(`units:${rawUnit}`, { count })
|
||||
: rawUnit
|
||||
}
|
||||
let unit = simplify(rawUnit),
|
||||
{ numerators = [], denominators = [] } = unit
|
||||
|
||||
// the unit '%' is only displayed when it is the only unit
|
||||
let merge = [...numerators, ...denominators]
|
||||
if (merge.length === 1 && merge[0] === '%') return '%'
|
||||
|
@ -26,10 +36,10 @@ export let serialiseUnit = rawUnit => {
|
|||
!n && !d
|
||||
? ''
|
||||
: n && !d
|
||||
? printUnits(numerators)
|
||||
? printUnits(numerators, count)
|
||||
: !n && d
|
||||
? `/${printUnits(denominators)}`
|
||||
: `${printUnits(numerators)} / ${printUnits(denominators)}`
|
||||
? `/${printUnits(denominators, 1)}`
|
||||
: `${printUnits(numerators, plural)} / ${printUnits(denominators, 1)}`
|
||||
|
||||
return string
|
||||
}
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
import i18next from 'i18next'
|
||||
import queryString from 'query-string'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
import enTranslations from './locales/en.yaml'
|
||||
import {
|
||||
getFromSessionStorage,
|
||||
getIframeOption,
|
||||
parseDataAttributes,
|
||||
setToSessionStorage
|
||||
} from './utils'
|
||||
import unitsTranslations from './locales/units.yaml'
|
||||
|
||||
let lang =
|
||||
getIframeOption('lang') ||
|
||||
(typeof location !== 'undefined' &&
|
||||
queryString.parse(location.search)['lang']) ||
|
||||
parseDataAttributes(getFromSessionStorage('lang')) ||
|
||||
new URLSearchParams(document.location.search.substring(1)).get('lang') ||
|
||||
sessionStorage?.getItem('lang')?.match(/^(fr|en)$/)?.[0] ||
|
||||
'fr'
|
||||
|
||||
setToSessionStorage('lang', lang)
|
||||
i18next.use(initReactI18next).init(
|
||||
{
|
||||
sessionStorage?.setItem('lang', lang)
|
||||
i18next
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: lang,
|
||||
resources: {
|
||||
fr: { units: unitsTranslations.fr },
|
||||
en: {
|
||||
translation: enTranslations
|
||||
translation: enTranslations,
|
||||
units: unitsTranslations.en
|
||||
}
|
||||
}
|
||||
},
|
||||
(err, t) => {
|
||||
console && console.error('Error from i18n load', err, t) //eslint-disable-line no-console
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch(err => console?.error('Error from i18n load', err))
|
||||
|
||||
export default i18next
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
fr:
|
||||
heure_plural: heures
|
||||
jour_plural: jours
|
||||
semaine_plural: semaines
|
||||
trimestre_plural: trimestres
|
||||
employé_plural: employés
|
||||
points_plural: points
|
||||
en:
|
||||
heure: hour
|
||||
heure_plural: hours
|
||||
jour: day
|
||||
jour_plural: days
|
||||
semaine: week
|
||||
semaine_plural: weeks
|
||||
trimestre: quarter
|
||||
trimestre_plural: quarters
|
||||
repas: meal
|
||||
repas_plural: meals
|
||||
employé: employee
|
||||
employé_plural: employees
|
File diff suppressed because it is too large
Load Diff
|
@ -4,18 +4,16 @@
|
|||
# bloquant :
|
||||
# - ?
|
||||
|
||||
- nom: douche
|
||||
douche:
|
||||
icônes: 🚿
|
||||
|
||||
- espace: douche
|
||||
nom: impact
|
||||
douche . impact:
|
||||
icônes: 🍃
|
||||
période: flexible
|
||||
unité: kgCO2eq
|
||||
formule: impact par douche * douche . nombre
|
||||
|
||||
- espace: douche
|
||||
nom: nombre
|
||||
douche . nombre:
|
||||
période: flexible
|
||||
question: Combien prenez-vous de douches ?
|
||||
unité: _
|
||||
|
@ -23,21 +21,17 @@
|
|||
suggestions:
|
||||
Une par jour: 30
|
||||
|
||||
- espace: douche
|
||||
nom: impact par douche
|
||||
douche . impact par douche:
|
||||
formule: impact par litre * litres d'eau
|
||||
|
||||
- espace: douche
|
||||
nom: impact par litre
|
||||
douche . impact par litre:
|
||||
formule: eau . impact par litre froid + chauffage . impact par litre
|
||||
|
||||
- espace: douche
|
||||
douche . litres d'eau:
|
||||
icônes: 🇱
|
||||
nom: litres d'eau
|
||||
formule: durée de la douche * litres par minute
|
||||
|
||||
- espace: douche
|
||||
nom: litres par minute
|
||||
douche . litres par minute:
|
||||
formule:
|
||||
variations:
|
||||
- si: pomme de douche économe
|
||||
|
@ -46,24 +40,21 @@
|
|||
références:
|
||||
économise l'eau: https://www.jeconomiseleau.org/index.php/particuliers/economies-par-usage/la-douche-et-le-bain
|
||||
|
||||
- espace: douche
|
||||
nom: pomme de douche économe
|
||||
douche . pomme de douche économe:
|
||||
question: Utilisez-vous une pomme de douche économe ?
|
||||
par défaut: non
|
||||
|
||||
- nom: eau
|
||||
eau:
|
||||
icônes: 💧
|
||||
|
||||
- espace: eau
|
||||
nom: impact par litre froid
|
||||
eau . impact par litre froid:
|
||||
unité: kgCO2eq/l
|
||||
formule: 0.000132
|
||||
|
||||
- nom: chauffage
|
||||
chauffage:
|
||||
icônes: 🔥
|
||||
|
||||
- espace: chauffage
|
||||
nom: type
|
||||
chauffage . type:
|
||||
question: Comment est chauffée votre eau ?
|
||||
formule:
|
||||
une possibilité:
|
||||
|
@ -74,20 +65,16 @@
|
|||
- électricité
|
||||
par défaut: gaz
|
||||
|
||||
- espace: chauffage . type
|
||||
nom: gaz
|
||||
chauffage . type . gaz:
|
||||
icônes: 🔵
|
||||
- espace: chauffage . type
|
||||
nom: fioul
|
||||
chauffage . type . fioul:
|
||||
icônes: 🛢️
|
||||
- espace: chauffage . type
|
||||
nom: électricité
|
||||
chauffage . type . électricité:
|
||||
icônes: ⚡
|
||||
|
||||
# définir ces éléments un par un
|
||||
|
||||
- espace: chauffage
|
||||
nom: impact par kWh
|
||||
chauffage . impact par kWh:
|
||||
unité: kgCO2eq/kWh PCI
|
||||
formule:
|
||||
variations:
|
||||
|
@ -107,15 +94,13 @@
|
|||
électricité: https://www.electricitymap.org/?page=country&solar=false&remote=true&wind=false&countryCode=FR
|
||||
électricité sur Décrypter l'Energie: https://decrypterlenergie.org/decryptage-quel-est-le-contenu-en-co2-du-kwh-electrique
|
||||
|
||||
- espace: chauffage
|
||||
nom: énergie consommée par litre
|
||||
chauffage . énergie consommée par litre:
|
||||
formule: 0.0325
|
||||
unité: kWh
|
||||
références:
|
||||
analyse du prix d'une douche: https://www.econologie.com/forums/plomberie-et-sanitaire/prix-reel-d-un-bain-ou-d-une-douche-pour-l-eau-et-chauffage-t12727.html
|
||||
|
||||
- espace: chauffage
|
||||
nom: impact par litre
|
||||
chauffage . impact par litre:
|
||||
formule: impact par kWh * énergie consommée par litre
|
||||
|
||||
# Meilleure syntaxe : nouveau mécanisme correspondance
|
||||
|
@ -126,8 +111,7 @@
|
|||
# fioul: 50
|
||||
# électricité: 2
|
||||
|
||||
- espace: douche
|
||||
nom: durée de la douche
|
||||
douche . durée de la douche:
|
||||
question: Combien de temps dure votre douche en général ?
|
||||
unité: _
|
||||
par défaut: 5
|
||||
|
|
|
@ -166,35 +166,6 @@ contrat salarié . indemnité kilométrique vélo . active:
|
|||
revenu. Pour verser une prime de salaire équivalente à son salarié sans ce
|
||||
dispositif, **l'employeur devrait débourser près de 500€ pour un salaire
|
||||
médian**.
|
||||
contrat salarié . CDD . CIF:
|
||||
description.en: >-
|
||||
Contribution to the financing of individual training leave, specific to
|
||||
fixed-term contracts.
|
||||
description.fr: >-
|
||||
Contribution au financement du congé individuel de formation spécifique aux
|
||||
CDD.
|
||||
titre.en: CIF
|
||||
titre.fr: CIF
|
||||
contrat salarié . CDD . compensation pour congés non pris:
|
||||
description.en: >-
|
||||
The employee on a fixed-term contract has the same rights for paid leave as
|
||||
the employee on a permanent contract. He acquires and takes his paid leave
|
||||
under the same conditions.
|
||||
|
||||
|
||||
It is however common that the employee can not take all his leave before the
|
||||
end of his contract. In that case, he receives a compensatory alowance paid
|
||||
by the employer.
|
||||
description.fr: >
|
||||
Le salarié en CDD bénéficie des mêmes droits à congés payés que le salarié
|
||||
en CDI. Il acquiert et prend ses congés payés dans les mêmes conditions.
|
||||
|
||||
|
||||
Il est cependant courant que le salarié ne puisse pas prendre tous ses
|
||||
congés avant le terme de son contrat, il bénéficie alors d'une indemnité
|
||||
compensatrice de congés payés versée par l'employeur.
|
||||
titre.en: untaken vacation compensation
|
||||
titre.fr: compensation pour congés non pris
|
||||
? contrat salarié . CDD . compensation pour congés non pris . proportion congés non pris
|
||||
: titre.en: proportion of untaken leave
|
||||
titre.fr: proportion congés non pris
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# Ce petit ensemble de règles a été historiquement utilisé pour tester l'externalisation du moteur, et est en train d'être réintégré progressivement dans la base centrale
|
||||
|
||||
- nom: chiffre affaires
|
||||
chiffre affaires:
|
||||
période: flexible
|
||||
unité: €
|
||||
|
||||
- nom: charges
|
||||
charges:
|
||||
période: flexible
|
||||
par défaut: 0
|
||||
unité: €
|
||||
|
||||
- nom: répartition salaire sur dividendes
|
||||
répartition salaire sur dividendes:
|
||||
par défaut: 0.5
|
||||
|
||||
- nom: impôt sur les sociétés
|
||||
impôt sur les sociétés:
|
||||
période: année
|
||||
formule:
|
||||
barème:
|
||||
|
@ -28,25 +28,22 @@
|
|||
références:
|
||||
fiche service-public.fr: https://www.service-public.fr/professionnels-entreprises/vosdroits/F23575
|
||||
|
||||
- nom: bénéfice
|
||||
bénéfice:
|
||||
période: flexible
|
||||
formule: chiffre affaires - salaire total
|
||||
|
||||
- nom: dividendes
|
||||
dividendes:
|
||||
|
||||
- espace: dividendes
|
||||
dividendes . brut:
|
||||
période: flexible
|
||||
nom: brut
|
||||
formule: bénéfice - impôt sur les sociétés
|
||||
|
||||
- espace: dividendes
|
||||
dividendes . net:
|
||||
période: flexible
|
||||
nom: net
|
||||
formule: brut - prélèvement forfaitaire unique
|
||||
|
||||
- nom: prélèvement forfaitaire unique
|
||||
dividendes . prélèvement forfaitaire unique:
|
||||
période: flexible
|
||||
espace: dividendes
|
||||
formule:
|
||||
multiplication:
|
||||
assiette: brut
|
||||
|
@ -54,10 +51,10 @@
|
|||
- taux: 17.2%
|
||||
- taux: 12.8%
|
||||
|
||||
- nom: salaire total
|
||||
salaire total:
|
||||
période: flexible
|
||||
formule: chiffre affaires * répartition salaire sur dividendes
|
||||
|
||||
- nom: revenu net après impôt
|
||||
revenu net après impôt:
|
||||
période: flexible
|
||||
formule: contrat salarié . rémunération . net après impôt + dividendes . net
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
retrievePersistedSimulation
|
||||
} from '../../storage/persistSimulation'
|
||||
import Tracker, { devTracker } from '../../Tracker'
|
||||
import { inIframe, setToSessionStorage } from '../../utils'
|
||||
import { inIframe } from '../../utils'
|
||||
import './App.css'
|
||||
import Footer from './layout/Footer/Footer'
|
||||
import { PrivacyContent } from './layout/Footer/Privacy'
|
||||
|
@ -59,7 +59,7 @@ const middlewares = [
|
|||
|
||||
function InFranceRoute({ basename, language }) {
|
||||
useEffect(() => {
|
||||
setToSessionStorage('lang', language)
|
||||
sessionStorage?.setItem('lang', language)
|
||||
}, [language])
|
||||
const paths = constructLocalizedSitePath(language)
|
||||
const rules = language === 'en' ? baseRulesEn : baseRulesFr
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
- nom: revenu imposable
|
||||
revenu imposable:
|
||||
format: euros
|
||||
|
||||
- nom: revenu abattu
|
||||
revenu abattu:
|
||||
formule:
|
||||
allègement:
|
||||
assiette: revenu imposable
|
||||
abattement: 10%
|
||||
|
||||
- nom: impôt sur le revenu
|
||||
impôt sur le revenu:
|
||||
formule:
|
||||
barème:
|
||||
assiette: revenu abattu
|
||||
|
@ -26,8 +26,7 @@
|
|||
- au-dessus de: 153783
|
||||
taux: 45%
|
||||
|
||||
|
||||
- nom: impôt final
|
||||
impôt final:
|
||||
formule:
|
||||
allègement:
|
||||
assiette: impôt sur le revenu
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
- espace: douche
|
||||
nom: impact par douche
|
||||
douche . impact par douche:
|
||||
titre: Une douche
|
||||
icônes: 🚿
|
||||
formule: impact par litre * litres d'eau
|
||||
|
||||
- espace: douche
|
||||
nom: impact par litre
|
||||
douche . impact par litre:
|
||||
formule: eau . impact par litre froid + chauffage . impact par litre
|
||||
|
||||
- espace: douche
|
||||
nom: litres d'eau
|
||||
douche . litres d'eau:
|
||||
formule: durée de la douche * litres par minute
|
||||
|
||||
- espace: douche
|
||||
nom: litres par minute
|
||||
douche . litres par minute:
|
||||
unité: l/minute
|
||||
formule:
|
||||
variations:
|
||||
|
@ -23,13 +19,11 @@
|
|||
références:
|
||||
- https://www.jeconomiseleau.org/index.php/particuliers/economies-par-usage/la-douche-et-le-bain
|
||||
|
||||
- espace: douche
|
||||
nom: pomme de douche économe
|
||||
douche . pomme de douche économe:
|
||||
question: Utilisez-vous une pomme de douche économe ?
|
||||
par défaut: non
|
||||
|
||||
- espace: douche
|
||||
nom: durée de la douche
|
||||
douche . durée de la douche:
|
||||
question: Combien de temps dure votre douche en général (en minutes) ?
|
||||
par défaut: 5
|
||||
unité: minute
|
||||
|
@ -38,15 +32,10 @@
|
|||
moyenne: 10
|
||||
lente: 20
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- nom: chauffage
|
||||
chauffage:
|
||||
icônes: 🔥
|
||||
|
||||
- espace: chauffage
|
||||
nom: type
|
||||
chauffage . type:
|
||||
question: Votre eau est chauffée comment ?
|
||||
formule:
|
||||
une possibilité:
|
||||
|
@ -57,10 +46,7 @@
|
|||
- électricité
|
||||
par défaut: gaz
|
||||
|
||||
|
||||
|
||||
- espace: chauffage
|
||||
nom: impact par kWh
|
||||
chauffage . impact par kWh:
|
||||
unité: kgCO₂e/kWh
|
||||
formule:
|
||||
variations:
|
||||
|
@ -79,17 +65,12 @@
|
|||
- https://www.electricitymap.org/?page=country&solar=false&remote=true&wind=false&countryCode=FR
|
||||
- https://decrypterlenergie.org/decryptage-quel-est-le-contenu-en-co2-du-kwh-electrique
|
||||
|
||||
|
||||
|
||||
|
||||
- espace: chauffage
|
||||
nom: énergie consommée par litre
|
||||
chauffage . énergie consommée par litre:
|
||||
formule: 0.0325
|
||||
unité: kWh
|
||||
références:
|
||||
- https://www.econologie.com/forums/plomberie-et-sanitaire/prix-reel-d-un-bain-ou-d-une-douche-pour-l-eau-et-chauffage-t12727.html
|
||||
|
||||
- espace: chauffage
|
||||
nom: impact par litre
|
||||
chauffage . impact par litre:
|
||||
titre: impact par litre chauffé
|
||||
formule: impact par kWh * énergie consommée par litre
|
||||
|
|
|
@ -4,31 +4,6 @@ import { map } from 'ramda'
|
|||
export let capitalise0 = (name: string) =>
|
||||
name && name[0].toUpperCase() + name.slice(1)
|
||||
|
||||
export let getUrl = () =>
|
||||
typeof window !== 'undefined' ? window.location.href.toString() : null
|
||||
|
||||
export let parseDataAttributes = (value: any) =>
|
||||
value === 'undefined'
|
||||
? undefined
|
||||
: value === null
|
||||
? null
|
||||
: !isNaN(value)
|
||||
? +value
|
||||
: /* value is a normal string */
|
||||
value
|
||||
|
||||
export let getIframeOption = (optionName: string) => {
|
||||
let url = getUrl(),
|
||||
hasOption = url?.includes(optionName + '=')
|
||||
return parseDataAttributes(
|
||||
hasOption && url.split(optionName + '=')[1].split('&')[0]
|
||||
)
|
||||
}
|
||||
|
||||
export function isNumeric(val: number) {
|
||||
return Number(parseFloat(val)) === val
|
||||
}
|
||||
|
||||
export function debounce<ArgType: any>(
|
||||
timeout: number,
|
||||
fn: ArgType => void
|
||||
|
@ -94,13 +69,3 @@ export const constructSitePaths = (
|
|||
sitePaths
|
||||
)
|
||||
})
|
||||
|
||||
export const getFromSessionStorage = softCatch<string, any>(where => {
|
||||
typeof sessionStorage !== 'undefined' ? sessionStorage[where] : null
|
||||
})
|
||||
|
||||
export const setToSessionStorage = softCatch<string, void>((where, what) => {
|
||||
if (typeof sessionStorage !== 'undefined') {
|
||||
sessionStorage[where] = what
|
||||
}
|
||||
})
|
||||
|
|
|
@ -16,11 +16,11 @@ describe('conversation', function() {
|
|||
it('should start with the first missing variable', function() {
|
||||
let rawRules = [
|
||||
// TODO - this won't work without the indirection, figure out why
|
||||
{ nom: 'startHere', formule: { somme: ['a', 'b'] }, espace: 'top' },
|
||||
{ nom: 'a', espace: 'top', formule: 'aa' },
|
||||
{ nom: 'b', espace: 'top', formule: 'bb' },
|
||||
{ nom: 'aa', question: '?', titre: 'a', espace: 'top' },
|
||||
{ nom: 'bb', question: '?', titre: 'b', espace: 'top' }
|
||||
{ nom: 'top . startHere', formule: { somme: ['a', 'b'] } },
|
||||
{ nom: 'top . a', formule: 'aa' },
|
||||
{ nom: 'top . b', formule: 'bb' },
|
||||
{ nom: 'top . aa', question: '?', titre: 'a' },
|
||||
{ nom: 'top . bb', question: '?', titre: 'b' }
|
||||
],
|
||||
rules = rawRules.map(enrichRule),
|
||||
state = merge(baseState, {
|
||||
|
@ -34,16 +34,15 @@ describe('conversation', function() {
|
|||
let rawRules = [
|
||||
// TODO - this won't work without the indirection, figure out why
|
||||
{
|
||||
nom: 'startHere',
|
||||
formule: { somme: ['a', 'b', 'c'] },
|
||||
espace: 'top'
|
||||
nom: 'top . startHere',
|
||||
formule: { somme: ['a', 'b', 'c'] }
|
||||
},
|
||||
{ nom: 'a', espace: 'top', formule: 'aa' },
|
||||
{ nom: 'b', espace: 'top', formule: 'bb' },
|
||||
{ nom: 'c', espace: 'top', formule: 'cc' },
|
||||
{ nom: 'aa', question: '?', titre: 'a', espace: 'top' },
|
||||
{ nom: 'bb', question: '?', titre: 'b', espace: 'top' },
|
||||
{ nom: 'cc', question: '?', titre: 'c', espace: 'top' }
|
||||
{ nom: 'top . a', formule: 'aa' },
|
||||
{ nom: 'top . b', formule: 'bb' },
|
||||
{ nom: 'top . c', formule: 'cc' },
|
||||
{ nom: 'top . aa', question: '?', titre: 'a' },
|
||||
{ nom: 'top . bb', question: '?', titre: 'b' },
|
||||
{ nom: 'top . cc', question: '?', titre: 'c' }
|
||||
],
|
||||
rules = rawRules.map(enrichRule)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ describe('pay slip selector', function() {
|
|||
// $FlowFixMe
|
||||
let cotisationsSanté = (cotisations.find(([branche]) =>
|
||||
branche.includes('santé')
|
||||
) || [])[1].map(cotisation => cotisation.nom)
|
||||
) || [])[1].map(cotisation => cotisation.name)
|
||||
expect(cotisationsSanté).to.have.lengthOf(2)
|
||||
expect(cotisationsSanté).to.include('maladie')
|
||||
expect(cotisationsSanté).to.include('complémentaire santé')
|
||||
|
|
|
@ -13,19 +13,17 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'sum' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'sum . startHere',
|
||||
formule: 2,
|
||||
'non applicable si': 'sum . evt . ko',
|
||||
espace: 'sum'
|
||||
'non applicable si': 'sum . evt . ko'
|
||||
},
|
||||
{
|
||||
nom: 'evt',
|
||||
espace: 'sum',
|
||||
nom: 'sum . evt',
|
||||
formule: { 'une possibilité': ['ko'] },
|
||||
titre: 'Truc',
|
||||
question: '?'
|
||||
},
|
||||
{ nom: 'ko', espace: 'sum . evt' }
|
||||
{ nom: 'sum . evt . ko' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -37,15 +35,14 @@ describe('collectMissingVariables', function() {
|
|||
it('should identify missing variables mentioned in expressions', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'sum' },
|
||||
{ nom: 'evt', espace: 'sum' },
|
||||
{ nom: 'sum . evt' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'sum . startHere',
|
||||
formule: 2,
|
||||
'non applicable si': 'evt . nyet > evt . nope',
|
||||
espace: 'sum'
|
||||
'non applicable si': 'evt . nyet > evt . nope'
|
||||
},
|
||||
{ nom: 'nope', espace: 'sum . evt' },
|
||||
{ nom: 'nyet', espace: 'sum . evt' }
|
||||
{ nom: 'sum . evt . nope' },
|
||||
{ nom: 'sum . evt . nyet' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -59,12 +56,11 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'sum' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'sum . startHere',
|
||||
formule: 'trois',
|
||||
'non applicable si': '3 > 2',
|
||||
espace: 'sum'
|
||||
'non applicable si': '3 > 2'
|
||||
},
|
||||
{ nom: 'trois', espace: 'sum' }
|
||||
{ nom: 'sum . trois' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -77,14 +73,13 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'sum' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'sum . startHere',
|
||||
formule: 'trois',
|
||||
'non applicable si': {
|
||||
'une de ces conditions': ['3 > 2', 'trois']
|
||||
},
|
||||
espace: 'sum'
|
||||
}
|
||||
},
|
||||
{ nom: 'trois', espace: 'sum' }
|
||||
{ nom: 'sum . trois' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -96,11 +91,10 @@ describe('collectMissingVariables', function() {
|
|||
it('should report "une possibilité" as a missing variable even though it has a formula', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: 'trois', espace: 'top' },
|
||||
{ nom: 'top . startHere', formule: 'trois' },
|
||||
{
|
||||
nom: 'trois',
|
||||
formule: { 'une possibilité': ['ko'] },
|
||||
espace: 'top'
|
||||
nom: 'top . trois',
|
||||
formule: { 'une possibilité': ['ko'] }
|
||||
}
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
|
@ -113,12 +107,11 @@ describe('collectMissingVariables', function() {
|
|||
it('should not report missing variables when "une possibilité" is inapplicable', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: 'trois', espace: 'top' },
|
||||
{ nom: 'top . startHere', formule: 'trois' },
|
||||
{
|
||||
nom: 'trois',
|
||||
nom: 'top . trois',
|
||||
formule: { 'une possibilité': ['ko'] },
|
||||
'non applicable si': 1,
|
||||
espace: 'top'
|
||||
'non applicable si': 1
|
||||
}
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
|
@ -134,11 +127,10 @@ describe('collectMissingVariables', function() {
|
|||
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: 'trois', espace: 'top' },
|
||||
{ nom: 'top . startHere', formule: 'trois' },
|
||||
{
|
||||
nom: 'trois',
|
||||
formule: { 'une possibilité': ['ko'] },
|
||||
espace: 'top'
|
||||
nom: 'top . trois',
|
||||
formule: { 'une possibilité': ['ko'] }
|
||||
}
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
|
@ -152,17 +144,16 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
'aiguillage numérique': {
|
||||
'11 > dix': '1000%',
|
||||
'3 > dix': '1100%',
|
||||
'1 > dix': '1200%'
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', espace: 'top' }
|
||||
{ nom: 'top . dix' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -176,13 +167,11 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
formule: { somme: ['variations'] },
|
||||
espace: 'top'
|
||||
nom: 'top . startHere',
|
||||
formule: { somme: ['variations'] }
|
||||
},
|
||||
{
|
||||
nom: 'variations',
|
||||
espace: 'top',
|
||||
nom: 'top . variations',
|
||||
formule: {
|
||||
barème: {
|
||||
assiette: 2008,
|
||||
|
@ -213,10 +202,10 @@ describe('collectMissingVariables', function() {
|
|||
}
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', espace: 'top' },
|
||||
{ nom: 'deux', espace: 'top' },
|
||||
{ nom: 'trois', espace: 'top' },
|
||||
{ nom: 'quatre', espace: 'top' }
|
||||
{ nom: 'top . dix' },
|
||||
{ nom: 'top . deux' },
|
||||
{ nom: 'top . trois' },
|
||||
{ nom: 'top . quatre' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -233,16 +222,15 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
'aiguillage numérique': {
|
||||
'8 > 10': '1000%',
|
||||
'1 > 2': 'dix'
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', espace: 'top' }
|
||||
{ nom: 'top . dix' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -255,7 +243,7 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
'aiguillage numérique': {
|
||||
'10 > 11': '1000%',
|
||||
|
@ -264,11 +252,10 @@ describe('collectMissingVariables', function() {
|
|||
'1 > 2': '75015%'
|
||||
}
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'douze', espace: 'top' },
|
||||
{ nom: 'dix', espace: 'top' }
|
||||
{ nom: 'top . douze' },
|
||||
{ nom: 'top . dix' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -282,17 +269,16 @@ describe('collectMissingVariables', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
'aiguillage numérique': {
|
||||
'11 > 10': '1000%',
|
||||
'3 > dix': '1100%',
|
||||
'1 > dix': '1200%'
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', espace: 'top' }
|
||||
{ nom: 'top . dix' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'startHere')(stateSelector),
|
||||
|
@ -306,16 +292,14 @@ describe('nextSteps', function() {
|
|||
it('should generate questions for simple situations', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'sum', formule: 'deux', espace: 'top' },
|
||||
{ nom: 'top . sum', formule: 'deux' },
|
||||
{
|
||||
nom: 'deux',
|
||||
nom: 'top . deux',
|
||||
formule: 2,
|
||||
'non applicable si': 'top . sum . evt',
|
||||
espace: 'top'
|
||||
'non applicable si': 'top . sum . evt'
|
||||
},
|
||||
{
|
||||
nom: 'evt',
|
||||
espace: 'top . sum',
|
||||
nom: 'top . sum . evt',
|
||||
titre: 'Truc',
|
||||
question: '?'
|
||||
}
|
||||
|
@ -330,15 +314,13 @@ describe('nextSteps', function() {
|
|||
it('should generate questions', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'sum', formule: 'deux', espace: 'top' },
|
||||
{ nom: 'top . sum', formule: 'deux' },
|
||||
{
|
||||
nom: 'deux',
|
||||
formule: 'sum . evt',
|
||||
espace: 'top'
|
||||
nom: 'top . deux',
|
||||
formule: 'sum . evt'
|
||||
},
|
||||
{
|
||||
nom: 'evt',
|
||||
espace: 'top . sum',
|
||||
nom: 'top . sum . evt',
|
||||
question: '?'
|
||||
}
|
||||
],
|
||||
|
@ -355,21 +337,19 @@ describe('nextSteps', function() {
|
|||
it.skip('should generate questions with more intricate situation', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'sum', formule: { somme: [2, 'deux'] }, espace: 'top' },
|
||||
{ nom: 'top . sum', formule: { somme: [2, 'deux'] } },
|
||||
{
|
||||
nom: 'deux',
|
||||
nom: 'top . deux',
|
||||
formule: 2,
|
||||
'non applicable si': "top . sum . evt = 'ko'",
|
||||
espace: 'top'
|
||||
'non applicable si': "top . sum . evt = 'ko'"
|
||||
},
|
||||
{
|
||||
nom: 'evt',
|
||||
espace: 'top . sum',
|
||||
nom: 'top . sum . evt',
|
||||
formule: { 'une possibilité': ['ko'] },
|
||||
titre: 'Truc',
|
||||
question: '?'
|
||||
},
|
||||
{ nom: 'ko', espace: 'top . sum . evt' }
|
||||
{ nom: 'top . sum . evt . ko' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule)),
|
||||
analysis = analyse(rules, 'sum')(stateSelector),
|
||||
|
|
|
@ -10,7 +10,6 @@ import { analyse, parseAll } from '../source/engine/traverse'
|
|||
import { collectMissingVariables } from '../source/engine/generateQuestions'
|
||||
import testSuites from './load-mecanism-tests'
|
||||
import * as R from 'ramda'
|
||||
import { isNumeric } from '../source/utils'
|
||||
import { serialiseUnit } from 'Engine/units'
|
||||
|
||||
describe('Mécanismes', () =>
|
||||
|
@ -43,7 +42,7 @@ describe('Mécanismes', () =>
|
|||
missing = collectMissingVariables(analysis.targets),
|
||||
target = analysis.targets[0]
|
||||
|
||||
if (isNumeric(valeur)) {
|
||||
if (typeof valeur === 'number') {
|
||||
expect(target.nodeValue).to.be.closeTo(valeur, 0.001)
|
||||
} else if (valeur !== undefined) {
|
||||
expect(target).to.have.property('nodeValue', valeur)
|
||||
|
|
|
@ -140,8 +140,7 @@
|
|||
|
||||
- nom: CDD
|
||||
|
||||
- espace: CDD
|
||||
nom: poursuivi en CDI
|
||||
- nom: CDD . poursuivi en CDI
|
||||
|
||||
- test: variable booléene
|
||||
formule: CDD . poursuivi en CDI
|
||||
|
@ -188,10 +187,8 @@
|
|||
- commerciale
|
||||
- artisanale
|
||||
|
||||
- espace: catégorie d'activité
|
||||
nom: artisanale
|
||||
- espace: catégorie d'activité
|
||||
nom: commerciale
|
||||
- nom: catégorie d'activité . artisanale
|
||||
- nom: catégorie d'activité . commerciale
|
||||
|
||||
- test: test de possibilités
|
||||
formule: catégorie d'activité = 'artisanale'
|
||||
|
|
|
@ -16,7 +16,7 @@ describe('enrichRule', function() {
|
|||
})
|
||||
|
||||
it('should extract the dotted name of the rule', function() {
|
||||
let rule = { espace: 'contrat salarié', nom: 'CDD' }
|
||||
let rule = { nom: 'contrat salarié . CDD' }
|
||||
expect(enrichRule(rule)).to.have.property('name', 'CDD')
|
||||
expect(enrichRule(rule)).to.have.property(
|
||||
'dottedName',
|
||||
|
@ -77,8 +77,7 @@ describe('translateAll', function() {
|
|||
it('should translate flat rules', function() {
|
||||
let rules = [
|
||||
{
|
||||
espace: 'foo',
|
||||
nom: 'bar',
|
||||
nom: 'foo . bar',
|
||||
titre: 'Titre',
|
||||
description: 'Description',
|
||||
question: 'Question'
|
||||
|
@ -115,16 +114,14 @@ describe('misc', function() {
|
|||
it('should procude an array of the parents of a rule', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'CDD', question: 'CDD ?' },
|
||||
{ nom: 'taxe', formule: 'montant annuel / 12', espace: 'CDD' },
|
||||
{ nom: 'CDD . taxe', formule: 'montant annuel / 12' },
|
||||
{
|
||||
nom: 'montant annuel',
|
||||
formule: '20 - exonération annuelle',
|
||||
espace: 'CDD . taxe'
|
||||
nom: 'CDD . taxe . montant annuel',
|
||||
formule: '20 - exonération annuelle'
|
||||
},
|
||||
{
|
||||
nom: 'exonération annuelle',
|
||||
formule: 20,
|
||||
espace: 'CDD . taxe . montant annuel'
|
||||
nom: 'CDD . taxe . montant annuel . exonération annuelle',
|
||||
formule: 20
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -138,16 +135,14 @@ describe('misc', function() {
|
|||
it("should disambiguate a reference to another rule in a rule, given the latter's namespace", function() {
|
||||
let rawRules = [
|
||||
{ nom: 'CDD', question: 'CDD ?' },
|
||||
{ nom: 'taxe', formule: 'montant annuel / 12', espace: 'CDD' },
|
||||
{ nom: 'CDD . taxe', formule: 'montant annuel / 12' },
|
||||
{
|
||||
nom: 'montant annuel',
|
||||
formule: '20 - exonération annuelle',
|
||||
espace: 'CDD . taxe'
|
||||
nom: 'CDD . taxe . montant annuel',
|
||||
formule: '20 - exonération annuelle'
|
||||
},
|
||||
{
|
||||
nom: 'exonération annuelle',
|
||||
formule: 20,
|
||||
espace: 'CDD . taxe . montant annuel'
|
||||
nom: 'CDD . taxe . montant annuel . exonération annuelle',
|
||||
formule: 20
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ describe('analyse on raw rules', function() {
|
|||
it('should handle direct referencing of a variable', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: 'dix', espace: 'top' },
|
||||
{ nom: 'dix', formule: 10, espace: 'top' }
|
||||
{ nom: 'top . startHere', formule: 'dix' },
|
||||
{ nom: 'top . dix', formule: 10 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -38,8 +38,8 @@ describe('analyse on raw rules', function() {
|
|||
it('should handle expressions referencing other rules', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: '3259 + dix', espace: 'top' },
|
||||
{ nom: 'dix', formule: 10, espace: 'top' }
|
||||
{ nom: 'top . startHere', formule: '3259 + dix' },
|
||||
{ nom: 'top . dix', formule: 10 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -50,9 +50,9 @@ describe('analyse on raw rules', function() {
|
|||
it('should handle applicability conditions', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: '3259 + dix', espace: 'top' },
|
||||
{ nom: 'dix', formule: 10, espace: 'top', 'non applicable si': 'vrai' },
|
||||
{ nom: 'vrai', formule: '2 > 1', espace: 'top' }
|
||||
{ nom: 'top . startHere', formule: '3259 + dix' },
|
||||
{ nom: 'top . dix', formule: 10, 'non applicable si': 'vrai' },
|
||||
{ nom: 'top . vrai', formule: '2 > 1' }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -63,8 +63,8 @@ describe('analyse on raw rules', function() {
|
|||
it('should handle comparisons', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: '3259 > dix', espace: 'top' },
|
||||
{ nom: 'dix', formule: 10, espace: 'top' }
|
||||
{ nom: 'top . startHere', formule: '3259 > dix' },
|
||||
{ nom: 'top . dix', formule: 10 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -115,17 +115,16 @@ describe('analyse with mecanisms', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
'aiguillage numérique': {
|
||||
'1 > dix': '1000%',
|
||||
'3 < dix': '1100%',
|
||||
'3 > dix': '1200%'
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', formule: 10, espace: 'top' }
|
||||
{ nom: 'top . dix', formule: 10 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -134,10 +133,7 @@ describe('analyse with mecanisms', function() {
|
|||
})
|
||||
|
||||
it('should handle percentages', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', formule: '35%', espace: 'top' }
|
||||
],
|
||||
let rawRules = [{ nom: 'top' }, { nom: 'top . startHere', formule: '35%' }],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
analyse(rules, 'startHere')(stateSelector).targets[0]
|
||||
|
@ -323,11 +319,10 @@ describe('analyse with mecanisms', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
formule: { complément: { cible: 'dix', montant: 93 } },
|
||||
espace: 'top'
|
||||
nom: 'top . startHere',
|
||||
formule: { complément: { cible: 'dix', montant: 93 } }
|
||||
},
|
||||
{ nom: 'dix', formule: 17, espace: 'top' }
|
||||
{ nom: 'top . dix', formule: 17 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -339,16 +334,15 @@ describe('analyse with mecanisms', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
nom: 'top . startHere',
|
||||
formule: {
|
||||
complément: {
|
||||
cible: 'dix',
|
||||
composantes: [{ montant: 93 }, { montant: 93 }]
|
||||
}
|
||||
},
|
||||
espace: 'top'
|
||||
}
|
||||
},
|
||||
{ nom: 'dix', formule: 17, espace: 'top' }
|
||||
{ nom: 'top . dix', formule: 17 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
@ -359,10 +353,9 @@ describe('analyse with mecanisms', function() {
|
|||
it('should handle filtering on components', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{ nom: 'startHere', espace: 'top', formule: 'composed [salarié]' },
|
||||
{ nom: 'top . startHere', formule: 'composed [salarié]' },
|
||||
{
|
||||
nom: 'composed',
|
||||
espace: 'top',
|
||||
nom: 'top . composed',
|
||||
formule: {
|
||||
barème: {
|
||||
assiette: 2008,
|
||||
|
@ -399,14 +392,12 @@ describe('analyse with mecanisms', function() {
|
|||
let rawRules = [
|
||||
{ nom: 'top' },
|
||||
{
|
||||
nom: 'startHere',
|
||||
espace: 'top',
|
||||
nom: 'top . startHere',
|
||||
formule: 'composed [salarié] + composed [employeur]'
|
||||
},
|
||||
{ nom: 'orHere', espace: 'top', formule: 'composed' },
|
||||
{ nom: 'top . orHere', formule: 'composed' },
|
||||
{
|
||||
nom: 'composed',
|
||||
espace: 'top',
|
||||
nom: 'top . composed',
|
||||
formule: {
|
||||
barème: {
|
||||
assiette: 2008,
|
||||
|
@ -448,7 +439,7 @@ describe('Implicit parent applicability', function() {
|
|||
it('should make a variable non applicable if one parent is input to false', function() {
|
||||
let rawRules = [
|
||||
{ nom: 'CDD', question: 'CDD ?' },
|
||||
{ nom: 'surcoût', formule: 10, espace: 'CDD' }
|
||||
{ nom: 'CDD . surcoût', formule: 10 }
|
||||
],
|
||||
rules = parseAll(rawRules.map(enrichRule))
|
||||
expect(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect } from 'chai'
|
||||
import { evaluateBottomUp, getSituationValue } from '../source/engine/getSituationValue'
|
||||
import { getSituationValue } from '../source/engine/getSituationValue'
|
||||
|
||||
describe('getSituationValue', function() {
|
||||
it('should directly return the value of any rule that specifies a format (i.e currency, duration)', function() {
|
||||
|
@ -66,8 +66,7 @@ describe('getSituationValue', function() {
|
|||
|
||||
it('should set the value of variants to false if one of them is true', function() {
|
||||
let rule = {
|
||||
nom: 'ici',
|
||||
espace: 'univers',
|
||||
nom: 'univers . ici',
|
||||
formule: { 'une possibilité': ['noir', 'blanc'] }
|
||||
},
|
||||
state = { 'univers . ici': 'blanc' },
|
||||
|
|
Loading…
Reference in New Issue