Merge pull request #1067 from betagouv/api-meca

Travail sur les mécanismes
pull/1068/head
Maxime Quandalle 2020-06-08 16:58:05 +02:00 committed by GitHub
commit e3fa5b5859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 61 additions and 77 deletions

View File

@ -5,11 +5,10 @@ import { InfixMecanism } from '../components/mecanisms/common'
import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation'
import { simplifyNodeUnit } from '../nodeUnits'
import { mapTemporal, pureTemporal, temporalAverage } from '../temporal'
import { EvaluatedNode, EvaluatedRule, Evaluation } from '../types'
import { EvaluatedNode, EvaluatedRule } from '../types'
import { serializeUnit } from '../units'
type MecanismRoundProps = {
nodeValue: Evaluation<number>
explanation: ArrondiExplanation
}
@ -18,7 +17,7 @@ type ArrondiExplanation = {
decimals: EvaluatedNode<string, number>
}
function MecanismRound({ nodeValue, explanation }: MecanismRoundProps) {
function MecanismRound({ explanation }: MecanismRoundProps) {
return (
<InfixMecanism value={explanation.value}>
{explanation.decimals.nodeValue !== false &&
@ -75,7 +74,7 @@ function evaluate<Names extends string>(
}
}
export default (recurse, k, v) => {
export default (recurse, v) => {
const explanation = {
value: has('valeur', v) ? recurse(v['valeur']) : recurse(v),
decimals: has('décimales', v) ? recurse(v['décimales']) : defaultNode(0)

View File

@ -12,19 +12,9 @@ import {
evaluatePlafondUntilActiveTranche,
parseTranches
} from './trancheUtils'
import { decompose } from './utils'
import variations from './variations'
export default function parse(parse, k, v) {
// Barème en taux marginaux.
if (v.composantes) {
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {
return variations(parse, k, v, true)
}
// Barème en taux marginaux.
export default function parse(parse, v) {
const explanation = {
assiette: parse(v.assiette),
multiplicateur: v.multiplicateur ? parse(v.multiplicateur) : defaultNode(1),

View File

@ -16,7 +16,7 @@ const evaluate = (cache, situation, parsedRules, node) => {
return { ...node, nodeValue, explanation, missingVariables }
}
export const mecanismAllOf = (recurse, k, v) => {
export const mecanismAllOf = (recurse, v) => {
if (!is(Array, v)) throw new Error('should be array')
const explanation = map(recurse, v)
const jsx = ({ nodeValue, explanation, unit }) => (

View File

@ -26,7 +26,7 @@ const evaluate = (cache, situation, parsedRules, node) => {
return { ...node, nodeValue, explanation, missingVariables }
}
export const mecanismOneOf = (recurse, k, v) => {
export const mecanismOneOf = (recurse, v) => {
if (!is(Array, v)) throw new Error('should be array')
const explanation = map(recurse, v)
const jsx = ({ nodeValue, explanation, unit }) => (

View File

@ -69,7 +69,7 @@ const evaluate = (cache, situation, parsedRules, node) => {
}
}
export default (recurse, k, v) => {
export default (recurse, v) => {
const explanation = parseObject(recurse, objectShape, v)
return {

View File

@ -82,7 +82,7 @@ const evaluate = evaluateObject(
}
)
export default (recurse, k, v) => {
export default (recurse, v) => {
const explanation = parseObject(recurse, objectShape, v)
return {

View File

@ -1,8 +1,6 @@
import { lensPath, over } from 'ramda'
import grille from '../components/mecanisms/Grille'
import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation'
import { decompose } from '../mecanisms/utils'
import variations from '../mecanisms/variations'
import {
liftTemporal2,
liftTemporalNode,
@ -15,14 +13,7 @@ import {
parseTranches
} from './trancheUtils'
export default function parse(parse, k, v) {
if (v.composantes) {
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {
return variations(parse, k, v, true)
}
export default function parse(parse, v) {
const defaultUnit = v['unité'] && parseUnit(v['unité'])
const explanation = {
assiette: parse(v.assiette),

View File

@ -86,7 +86,7 @@ export const evaluateInversion = (oldCache, situation, parsedRules, node) => {
}
}
export const mecanismInversion = dottedName => (recurse, k, v) => {
export const mecanismInversion = dottedName => (recurse, v) => {
if (!v.avec) {
throw new Error(
"Une formule d'inversion doit préciser _avec_ quoi on peut inverser la variable"

View File

@ -2,7 +2,7 @@ import React from 'react'
import { Mecanism } from '../components/mecanisms/common'
import { evaluateArray, makeJsx } from '../evaluation'
export const mecanismMax = (recurse, k, v) => {
export const mecanismMax = (recurse, v) => {
const explanation = v.map(recurse)
const max = (a, b) => {

View File

@ -3,7 +3,7 @@ import React from 'react'
import { Mecanism } from '../components/mecanisms/common'
import { evaluateArray, makeJsx } from '../evaluation'
export const mecanismMin = (recurse, k, v) => {
export const mecanismMin = (recurse, v) => {
const explanation = v.map(recurse)
const evaluate = evaluateArray(min, Infinity)
const jsx = ({ nodeValue, explanation, unit }) => (

View File

@ -1,5 +1,5 @@
// TODO : This isn't a real mecanism, cf. #963
export const mecanismOnePossibility = dottedName => (recurse, k, v) => ({
export const mecanismOnePossibility = dottedName => (recurse, v) => ({
...v,
'une possibilité': 'oui',
evaluate: (cache, situation, parsedRules, node) => ({

View File

@ -8,7 +8,7 @@ import { inferUnit, serializeUnit } from '../units'
import { curry, map } from 'ramda'
import React from 'react'
export default (k, operatorFunction, symbol) => (recurse, k, v) => {
export default (k, operatorFunction, symbol) => (recurse, v) => {
const evaluate = (cache, situation, parsedRules, node) => {
const explanation = map(
curry(evaluateNode)(cache, situation, parsedRules),

View File

@ -1,19 +1,10 @@
import Product from '../components/mecanisms/Product'
import { typeWarning } from '../error'
import { defaultNode, evaluateObject, parseObject } from '../evaluation'
import { decompose } from './utils'
import variations from './variations'
import { convertNodeToUnit } from '../nodeUnits'
import { areUnitConvertible, convertUnit, inferUnit } from '../units'
export const mecanismProduct = (recurse, k, v) => {
if (v.composantes) {
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(recurse, k, v)
}
if (v.variations) {
return variations(recurse, k, v, true)
}
export const mecanismProduct = (recurse, v) => {
const objectShape = {
assiette: false,
taux: defaultNode(1),

View File

@ -45,7 +45,7 @@ const evaluateRecalcul = (cache, situation, parsedRules, node) => {
}
}
export const mecanismRecalcul = dottedNameContext => (recurse, k, v) => {
export const mecanismRecalcul = dottedNameContext => (recurse, v) => {
const amendedSituation = Object.keys(v.avec).map(dottedName => [
recurse(dottedName),
recurse(v.avec[dottedName])

View File

@ -5,7 +5,7 @@ import { defaultNode, evaluateObject, parseObject } from '../evaluation'
import { convertNodeToUnit } from '../nodeUnits'
import { parseUnit, serializeUnit } from '../units'
export const mecanismReduction = (recurse, k, v) => {
export const mecanismReduction = (recurse, v) => {
const objectShape = {
assiette: false,
abattement: defaultNode(0),

View File

@ -20,7 +20,7 @@ function stripTemporalTransform(node) {
}
return stripTemporalTransform(node.explanation.value)
}
export default function parse<Name extends string>(parse, k, v) {
export default function parse<Name extends string>(parse, v) {
const rule = parse(v.règle)
if (!v['valeurs cumulées']) {
throw new Error(

View File

@ -7,7 +7,7 @@ const evaluate = evaluateArray(
false
)
export const mecanismSum = (recurse, k, v) => {
export const mecanismSum = (recurse, v) => {
const explanation = v.map(recurse)
return {
evaluate,

View File

@ -33,7 +33,7 @@ const evaluate = (cache, situation, parsedRules, node) => {
return { ...node, nodeValue: safeNodeValue, explanation, missingVariables }
}
export const mecanismSynchronisation = (recurse, k, v) => {
export const mecanismSynchronisation = (recurse, v) => {
return {
explanation: { ...v, API: recurse(v.API) },
evaluate,

View File

@ -1,6 +1,4 @@
import { defaultNode, evaluateNode, mergeAllMissing } from '../evaluation'
import { decompose } from './utils'
import variations from './variations'
import tauxProgressif from '../components/mecanisms/TauxProgressif'
import { convertNodeToUnit } from '../nodeUnits'
import { parseUnit } from '../units'
@ -9,15 +7,7 @@ import {
parseTranches
} from './trancheUtils'
export default function parse(parse, k, v) {
if (v.composantes) {
//mécanisme de composantes. Voir mécanismes.md/composantes
return decompose(parse, k, v)
}
if (v.variations) {
return variations(parse, k, v, true)
}
export default function parse(parse, v) {
const explanation = {
assiette: parse(v.assiette),
multiplicateur: v.multiplicateur ? parse(v.multiplicateur) : defaultNode(1),

View File

@ -46,7 +46,7 @@ function evaluate(
}
}
export default function parseVariableTemporelle(parse, __, v: any) {
export default function parseVariableTemporelle(parse, v) {
const explanation = parse(v.explanation)
return {
evaluate,

View File

@ -12,15 +12,12 @@ import {
import { inferUnit } from '../units'
import { mergeAllMissing } from './../evaluation'
/* @devariate = true => This function will produce variations of a same mecanism (e.g. product) that share some common properties */
export default function parse(recurse, k, v, devariate) {
const explanation = devariate
? devariateExplanation(recurse, k, v)
: v.map(({ si, alors, sinon }) =>
sinon !== undefined
? { consequence: recurse(sinon), condition: defaultNode(true) }
: { consequence: recurse(alors), condition: recurse(si) }
)
export default function parse(recurse, v) {
const explanation = v.map(({ si, alors, sinon }) =>
sinon !== undefined
? { consequence: recurse(sinon), condition: defaultNode(true) }
: { consequence: recurse(alors), condition: recurse(si) }
)
// TODO - find an appropriate representation
return {
@ -36,6 +33,23 @@ export default function parse(recurse, k, v, devariate) {
)
}
}
export function devariate(recurse, k, v) {
const explanation = devariateExplanation(recurse, k, v)
return {
explanation,
evaluate,
jsx: Variations,
category: 'mecanism',
name: 'variations',
type: 'numeric',
unit: inferUnit(
'+',
explanation.map(r => r.consequence.unit)
)
}
}
type Variation =
| {
si: any
@ -44,7 +58,7 @@ type Variation =
| {
sinon: object
}
export const devariateExplanation = (
const devariateExplanation = (
recurse,
mecanismKey,
v: { variations: Array<Variation> }

View File

@ -1,7 +1,6 @@
// This should be the new way to implement mecanisms
// In a specific file
// TODO import them automatically
// TODO convert the legacy functions to new files
import mecanismRound, { unchainRoundMecanism } from './mecanisms/arrondi'
import barème from './mecanisms/barème'
import durée from './mecanisms/durée'
@ -11,7 +10,7 @@ import operation from './mecanisms/operation'
import régularisation from './mecanisms/régularisation'
import tauxProgressif from './mecanisms/tauxProgressif'
import variableTemporelle from './mecanisms/variableTemporelle'
import variations from './mecanisms/variations'
import variations, { devariate } from './mecanisms/variations'
import { Grammar, Parser } from 'nearley'
import {
add,
@ -43,6 +42,7 @@ import { mecanismSynchronisation } from './mecanisms/synchronisation'
import { mecanismRecalcul } from './mecanisms/recalcul'
import { parseReferenceTransforms } from './parseReference'
import { EvaluatedRule } from './types'
import { decompose } from './mecanisms/utils'
export const parse = (rules, rule, parsedRules) => rawNode => {
if (rawNode == null) {
@ -146,6 +146,7 @@ Cela vient probablement d'une erreur dans l'indentation
}
const parseFn = parseFunctions[mecanismName]
if (!parseFn) {
syntaxError(
rule.dottedName,
@ -155,7 +156,15 @@ Vérifiez qu'il n'y ait pas d'erreur dans l'orthographe du nom.`
)
}
try {
return parseFn(parse(rules, rule, parsedRules), mecanismName, values)
const recurse = parse(rules, rule, parsedRules)
// Mécanisme de composantes. Voir mécanismes.md/composantes
if (values?.composantes) {
return decompose(recurse, mecanismName, values)
}
if (values?.variations) {
return devariate(recurse, mecanismName, values)
}
return parseFn(recurse, values)
} catch (e) {
if (e instanceof EngineError) {
throw e
@ -232,8 +241,8 @@ const statelessParseFunction = {
allègement: mecanismReduction,
variations,
synchronisation: mecanismSynchronisation,
valeur: (recurse, __, v) => recurse(v),
constant: (_, __, v) => ({
valeur: (recurse, v) => recurse(v),
constant: (_, v) => ({
type: v.type,
constant: true,
nodeValue: v.nodeValue,