Unités des barèmes et composantes
parent
0d0fcabe1b
commit
6606bb4f34
|
@ -77,6 +77,7 @@ export default withLanguage(
|
|||
|
||||
return nodeValue == undefined ? null : (
|
||||
<span css={style(customCSS)} className="value">
|
||||
unit: {unitText}
|
||||
{negative ? '-' : ''}
|
||||
{formattedValue}
|
||||
</span>
|
||||
|
|
|
@ -620,62 +620,6 @@ export let mecanismProduct = (recurse, k, v) => {
|
|||
}
|
||||
}
|
||||
|
||||
/* on réécrit en une syntaxe plus bas niveau mais plus régulière les tranches :
|
||||
`en-dessous de: 1`
|
||||
devient
|
||||
```
|
||||
de: 0
|
||||
à: 1
|
||||
```
|
||||
*/
|
||||
|
||||
export let mecanismLinearScale = (recurse, k, v) => {
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
return decompose(recurse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
return mecanismVariations(recurse, k, v, true)
|
||||
}
|
||||
let tranches = desugarScale(recurse)(v['tranches']),
|
||||
objectShape = {
|
||||
assiette: false,
|
||||
multiplicateur: defaultNode(1)
|
||||
}
|
||||
|
||||
let effect = ({ assiette, multiplicateur, tranches }) => {
|
||||
if (val(assiette) === null) return null
|
||||
|
||||
let roundedAssiette = Math.round(val(assiette))
|
||||
|
||||
let matchedTranche = tranches.find(
|
||||
({ de: min, à: max }) =>
|
||||
roundedAssiette >= val(multiplicateur) * min &&
|
||||
roundedAssiette <= max * val(multiplicateur)
|
||||
)
|
||||
|
||||
if (!matchedTranche) return 0
|
||||
if (matchedTranche.taux)
|
||||
return matchedTranche.taux.nodeValue * val(assiette)
|
||||
return matchedTranche.montant
|
||||
}
|
||||
|
||||
let explanation = {
|
||||
...parseObject(recurse, objectShape, v),
|
||||
tranches
|
||||
},
|
||||
evaluate = evaluateObject(objectShape, effect)
|
||||
|
||||
return {
|
||||
evaluate,
|
||||
jsx: Barème('linéaire'),
|
||||
explanation,
|
||||
category: 'mecanism',
|
||||
name: 'barème linéaire',
|
||||
barème: 'en taux',
|
||||
type: 'numeric'
|
||||
}
|
||||
}
|
||||
|
||||
export let mecanismContinuousScale = (recurse, k, v) => {
|
||||
let objectShape = {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { defaultNode, evaluateObject } from 'Engine/evaluation'
|
||||
import BarèmeContinu from 'Engine/mecanismViews/BarèmeContinu'
|
||||
import { val, anyNull } from 'Engine/traverse-common-functions'
|
||||
import { parseUnit } from 'Engine/units'
|
||||
import { parseObject } from 'Engine/evaluation'
|
||||
import { reduce, toPairs, sort, aperture, pipe, reduced, last } from 'ramda'
|
||||
|
||||
export default (recurse, k, v) => {
|
||||
let objectShape = {
|
||||
assiette: false,
|
||||
multiplicateur: defaultNode(1)
|
||||
}
|
||||
|
||||
let returnRate = v['retourne seulement le taux'] === 'oui'
|
||||
let effect = ({ assiette, multiplicateur, points }) => {
|
||||
if (anyNull([assiette, multiplicateur])) return null
|
||||
//We'll build a linear function given the two constraints that must be respected
|
||||
let result = pipe(
|
||||
toPairs,
|
||||
// we don't rely on the sorting of objects
|
||||
sort(([k1], [k2]) => k1 - k2),
|
||||
points => [...points, [Infinity, last(points)[1]]],
|
||||
aperture(2),
|
||||
reduce((_, [[lowerLimit, lowerRate], [upperLimit, upperRate]]) => {
|
||||
let x1 = val(multiplicateur) * lowerLimit,
|
||||
x2 = val(multiplicateur) * upperLimit,
|
||||
y1 = val(assiette) * val(recurse(lowerRate)),
|
||||
y2 = val(assiette) * val(recurse(upperRate))
|
||||
if (val(assiette) > x1 && val(assiette) <= x2) {
|
||||
// Outside of these 2 limits, it's a linear function a * x + b
|
||||
let a = (y2 - y1) / (x2 - x1),
|
||||
b = y1 - x1 * a,
|
||||
nodeValue = a * val(assiette) + b,
|
||||
taux = nodeValue / val(assiette)
|
||||
return reduced({
|
||||
nodeValue: returnRate ? taux : nodeValue,
|
||||
additionalExplanation: {
|
||||
seuil: val(assiette) / val(multiplicateur),
|
||||
taux
|
||||
}
|
||||
})
|
||||
}
|
||||
}, 0)
|
||||
)(points)
|
||||
|
||||
return result
|
||||
}
|
||||
let explanation = {
|
||||
...parseObject(recurse, objectShape, v),
|
||||
points: v.points,
|
||||
returnRate
|
||||
},
|
||||
evaluate = evaluateObject(objectShape, effect)
|
||||
return {
|
||||
evaluate,
|
||||
jsx: BarèmeContinu,
|
||||
explanation,
|
||||
category: 'mecanism',
|
||||
name: 'barème continu',
|
||||
type: 'numeric',
|
||||
unit: returnRate ? parseUnit('%') : explanation.assiette.unit
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
import { defaultNode, evaluateObject } from 'Engine/evaluation'
|
||||
import Barème from 'Engine/mecanismViews/Barème'
|
||||
import { mecanismVariations } from 'Engine/mecanisms'
|
||||
import { decompose } from 'Engine/mecanisms/utils'
|
||||
import { val } from 'Engine/traverse-common-functions'
|
||||
import { inferUnit, parseUnit } from 'Engine/units'
|
||||
import { parseObject } from 'Engine/evaluation'
|
||||
import { desugarScale } from './barème'
|
||||
/* on réécrit en une syntaxe plus bas niveau mais plus régulière les tranches :
|
||||
`en-dessous de: 1`
|
||||
devient
|
||||
```
|
||||
de: 0
|
||||
à: 1
|
||||
```
|
||||
*/
|
||||
|
||||
export default (recurse, k, v) => {
|
||||
if (v.composantes) {
|
||||
//mécanisme de composantes. Voir known-mecanisms.md/composantes
|
||||
return decompose(recurse, k, v)
|
||||
}
|
||||
if (v.variations) {
|
||||
return mecanismVariations(recurse, k, v, true)
|
||||
}
|
||||
let tranches = desugarScale(recurse)(v['tranches']),
|
||||
objectShape = {
|
||||
assiette: false,
|
||||
multiplicateur: defaultNode(1)
|
||||
}
|
||||
|
||||
let effect = ({ assiette, multiplicateur, tranches }) => {
|
||||
if (val(assiette) === null) return null
|
||||
|
||||
let roundedAssiette = Math.round(val(assiette))
|
||||
|
||||
let matchedTranche = tranches.find(
|
||||
({ de: min, à: max }) =>
|
||||
roundedAssiette >= val(multiplicateur) * min &&
|
||||
roundedAssiette <= max * val(multiplicateur)
|
||||
)
|
||||
|
||||
if (!matchedTranche) return 0
|
||||
if (matchedTranche.taux)
|
||||
return matchedTranche.taux.nodeValue * val(assiette)
|
||||
return matchedTranche.montant
|
||||
}
|
||||
|
||||
let explanation = {
|
||||
...parseObject(recurse, objectShape, v),
|
||||
tranches
|
||||
},
|
||||
evaluate = evaluateObject(objectShape, effect)
|
||||
|
||||
console.log('explanation', explanation)
|
||||
|
||||
return {
|
||||
evaluate,
|
||||
jsx: Barème('linéaire'),
|
||||
explanation,
|
||||
category: 'mecanism',
|
||||
name: 'barème linéaire',
|
||||
barème: 'en taux',
|
||||
type: 'numeric',
|
||||
|
||||
unit: explanation.assiette.unit
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import { decompose } from 'Engine/mecanisms/utils'
|
|||
import Barème from 'Engine/mecanismViews/Barème'
|
||||
import { val } from 'Engine/traverse-common-functions'
|
||||
import { evolve, has, pluck, sum } from 'ramda'
|
||||
import { inferUnit, parseUnit } from 'Engine/units'
|
||||
|
||||
export let desugarScale = recurse => tranches =>
|
||||
tranches
|
||||
|
@ -85,6 +86,7 @@ export default (recurse, k, v) => {
|
|||
jsx: Barème('marginal'),
|
||||
category: 'mecanism',
|
||||
name: 'barème',
|
||||
barème: 'marginal'
|
||||
barème: 'marginal',
|
||||
unit: inferUnit('*', [explanation.assiette.unit, parseUnit('%')])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import Composantes from 'Engine/mecanismViews/Composantes'
|
||||
import { add, dissoc, objOf } from 'ramda'
|
||||
import { evaluateArrayWithFilter } from 'Engine/evaluation'
|
||||
import { inferUnit } from 'Engine/units'
|
||||
|
||||
export let decompose = (recurse, k, v) => {
|
||||
let subProps = dissoc('composantes')(v),
|
||||
|
@ -28,7 +29,8 @@ export let decompose = (recurse, k, v) => {
|
|||
evaluate: evaluateArrayWithFilter(filter, add, 0),
|
||||
category: 'mecanism',
|
||||
name: 'composantes',
|
||||
type: 'numeric'
|
||||
type: 'numeric',
|
||||
unit: inferUnit('+', explanation.map(e => e.unit))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
// TODO import them automatically
|
||||
// TODO convert the legacy functions to new files
|
||||
import barème from 'Engine/mecanisms/barème.js'
|
||||
import barèmeContinu from 'Engine/mecanisms/barème-continu.js'
|
||||
import barèmeLinéaire from 'Engine/mecanisms/barème-linéaire.js'
|
||||
import { Parser } from 'nearley'
|
||||
import {
|
||||
add,
|
||||
|
@ -30,10 +32,8 @@ import Grammar from './grammar.ne'
|
|||
import {
|
||||
mecanismAllOf,
|
||||
mecanismComplement,
|
||||
mecanismContinuousScale,
|
||||
mecanismError,
|
||||
mecanismInversion,
|
||||
mecanismLinearScale,
|
||||
mecanismMax,
|
||||
mecanismMin,
|
||||
mecanismNumericalSwitch,
|
||||
|
@ -46,10 +46,7 @@ import {
|
|||
mecanismOnePossibility
|
||||
} from './mecanisms'
|
||||
import { Node } from './mecanismViews/common'
|
||||
import {
|
||||
parseReference,
|
||||
parseReferenceTransforms
|
||||
} from './parseReference'
|
||||
import { parseReferenceTransforms } from './parseReference'
|
||||
import { inferUnit } from 'Engine/units'
|
||||
|
||||
export let parse = (rules, rule, parsedRules) => rawNode => {
|
||||
|
@ -140,8 +137,8 @@ export let parseObject = (rules, rule, parsedRules) => rawNode => {
|
|||
somme: mecanismSum,
|
||||
multiplication: mecanismProduct,
|
||||
barème,
|
||||
'barème linéaire': mecanismLinearScale,
|
||||
'barème continu': mecanismContinuousScale,
|
||||
'barème linéaire': barèmeLinéaire,
|
||||
'barème continu': barèmeContinu,
|
||||
'le maximum de': mecanismMax,
|
||||
'le minimum de': mecanismMin,
|
||||
complément: mecanismComplement,
|
||||
|
|
|
@ -23,6 +23,7 @@ export let serialiseUnit = rawUnit => {
|
|||
? `/${denominators.join('')}`
|
||||
: `${numerators.join('')} / ${denominators.join('')}`
|
||||
|
||||
// the unit '%' is only displayed when it is the only unit
|
||||
if (string.length > 1) return string.replace(/%/g, '')
|
||||
return string
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ describe('Mécanismes', () =>
|
|||
}
|
||||
|
||||
if (unit) {
|
||||
expect(target.unit).not.to.be.equal(undefined)
|
||||
expect(serialiseUnit(target.unit)).to.eql(unit)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
- nom: base
|
||||
unité: _
|
||||
unité: £
|
||||
formule: 300
|
||||
|
||||
- nom: assiette
|
||||
unité: _
|
||||
unité: £
|
||||
|
||||
- test: Simple
|
||||
formule:
|
||||
|
@ -14,7 +14,7 @@
|
|||
0: 0%
|
||||
0.4: 3.16%
|
||||
1.1: 6.35%
|
||||
|
||||
unité attendue: £
|
||||
exemples:
|
||||
- nom: Premier point
|
||||
situation:
|
||||
|
@ -39,11 +39,12 @@
|
|||
|
||||
|
||||
- nom: base deux
|
||||
unité: _
|
||||
unité: µ
|
||||
formule: 300
|
||||
|
||||
- nom: assiette deux
|
||||
unité: _
|
||||
unité: µ
|
||||
|
||||
- test: Retour de taux, pas d'assiette
|
||||
formule:
|
||||
barème continu:
|
||||
|
@ -54,6 +55,7 @@
|
|||
0.75: 100%
|
||||
1: 0%
|
||||
retourne seulement le taux: oui
|
||||
unité attendue: '%'
|
||||
exemples:
|
||||
- nom: Premier point
|
||||
situation:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
taux: 10%
|
||||
- au-dessus de: 2000
|
||||
taux: 15%
|
||||
unité attendue: €
|
||||
|
||||
exemples:
|
||||
- nom: "petite assiette"
|
||||
|
@ -51,6 +52,7 @@
|
|||
- au-dessus de: 2000
|
||||
montant: 400
|
||||
|
||||
unité attendue: €
|
||||
exemples:
|
||||
- nom: "petite assiette"
|
||||
situation:
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
taux: 3%
|
||||
- au-dessus de: 3
|
||||
taux: 1%
|
||||
|
||||
|
||||
unité attendue: €
|
||||
exemples:
|
||||
- nom: 'petite assiette'
|
||||
situation:
|
||||
|
@ -52,6 +51,7 @@
|
|||
taux: 9%
|
||||
- au-dessus de: 2
|
||||
taux: 29%
|
||||
unité attendue: €
|
||||
|
||||
exemples:
|
||||
- nom:
|
||||
|
@ -62,12 +62,14 @@
|
|||
|
||||
- nom: ma condition
|
||||
|
||||
- nom: taux variable
|
||||
- test: taux variable
|
||||
formule:
|
||||
variations:
|
||||
- si: ma condition
|
||||
alors: 29%
|
||||
- sinon: 56%
|
||||
unité attendue: '%'
|
||||
exemples: []
|
||||
|
||||
- nom: deuxième barème
|
||||
test: Barème à taux variable
|
||||
|
@ -80,6 +82,7 @@
|
|||
taux: taux variable
|
||||
- au-dessus de: 1
|
||||
taux: 90%
|
||||
unité attendue: €
|
||||
|
||||
exemples:
|
||||
- nom: taux faible
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
- test: Composantes
|
||||
formule:
|
||||
multiplication:
|
||||
assiette: 100
|
||||
assiette: richesse
|
||||
composantes:
|
||||
- taux: 8%
|
||||
- taux: 2%
|
||||
|
||||
unité attendue: crédits
|
||||
exemples:
|
||||
- nom:
|
||||
situation:
|
||||
valeur attendue: 10
|
||||
|
||||
- nom: richesse
|
||||
unité: crédits
|
||||
formule: 100
|
||||
|
|
Loading…
Reference in New Issue