⚙️ Nouveau mécanisme barème continu

publicodes
Mael 2018-12-05 18:19:11 +01:00
parent 7394730fe3
commit 398595b8cc
4 changed files with 106 additions and 2 deletions

View File

@ -136,6 +136,13 @@ barème linéaire:
Il est composé de tranches qui se suivent. Il suffit de trouver l'assiette qui correspond à la tranche, et de multiplier le taux associé avec l'assiette.
Un montant fixe pour chaque tranche peut aussi remplacer le taux, rendant le barème encore plus simple, mais moins "juste", car moins continu.
barème continu:
type: numeric
description: |
Ce barème définit des points A(x1, y1) B(x2, y2) C(x3, y3) etc. On trace alors une droite entre ces points. x correspond à l'assiette du barème, et y au taux qui va être appliqué à l'assiette pour déterminer le montant du calcul.
Les x1, x2, peuvent éventuellement être des unités d'un multiplicateur.
complément:
type: numeric
description: |

View File

@ -3,7 +3,6 @@ import {
path,
mergeWith,
objOf,
toPairs,
dissoc,
add,
find,
@ -27,7 +26,12 @@ import {
subtract,
sum,
isNil,
reject
reject,
aperture,
sort,
toPairs,
reduced,
last
} from 'ramda'
import React from 'react'
import { Trans } from 'react-i18next'
@ -779,6 +783,57 @@ export let mecanismScale = (recurse, k, v) => {
}
}
export let mecanismContinuousScale = (recurse, k, v) => {
let objectShape = {
assiette: false,
multiplicateur: constantNode(1)
}
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
return 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
return reduced(a * val(assiette) + b)
}
}, 0)
)(points)
}
let explanation = {
...parseObject(recurse, objectShape, v),
points: v.points
},
evaluate = evaluateObject(objectShape, effect)
let jsx = (nodeValue, explanation) => (
<Node
classes="mecanism réductionLinéaire"
name="réductionLinéaire"
value={nodeValue}
child={<div> Réduction linéaire </div>}
/>
)
return {
evaluate,
jsx,
explanation,
category: 'mecanism',
name: 'réduction linéaire',
type: 'numeric'
}
}
export let mecanismMax = (recurse, k, v) => {
let explanation = v.map(recurse)

View File

@ -39,6 +39,7 @@ import {
mecanismProduct,
mecanismScale,
mecanismLinearScale,
mecanismContinuousScale,
mecanismMax,
mecanismMin,
mecanismError,
@ -252,6 +253,7 @@ export let treatObject = (rules, rule, treatOptions) => rawNode => {
multiplication: mecanismProduct,
barème: mecanismScale,
'barème linéaire': mecanismLinearScale,
'barème continu': mecanismContinuousScale,
'le maximum de': mecanismMax,
'le minimum de': mecanismMin,
complément: mecanismComplement,

View File

@ -0,0 +1,40 @@
- nom: base
format: nombre
formule: 300
- nom: assiette
format: nombre
- test: Simple
formule:
barème continu:
assiette: assiette
multiplicateur: base
points:
0: 0%
0.4: 3.16%
1.1: 6.35%
exemples:
- nom: Premier intervale
situation:
assiette: 10
valeur attendue: 0.026
- nom: Deuxième intervale
situation:
assiette: 120
valeur attendue: 3.792
- nom: Premier point
situation:
assiette: 150
valeur attendue: 5.423
- nom: Deuxième point
situation:
assiette: 330
valeur attendue: 20.955
- nom: Au-delà
situation:
assiette: 1000
valeur attendue: 63.5