Skip to content

Commit

Permalink
⚙️ ajoute les variables temporelles pour la variation
Browse files Browse the repository at this point in the history
  • Loading branch information
Johan Girod committed Feb 28, 2020
1 parent 71d04cb commit e06db01
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 126 deletions.
21 changes: 18 additions & 3 deletions source/engine/mecanisms/operation.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { convertToDate } from 'Engine/date'
import { typeWarning } from 'Engine/error'
import { evaluateNode, makeJsx, mergeMissing } from 'Engine/evaluation'
import { Node } from 'Engine/mecanismViews/common'
Expand All @@ -7,6 +8,7 @@ import { inferUnit, serializeUnit } from 'Engine/units'
import { curry, map } from 'ramda'
import React from 'react'

const comparisonOperator = ['≠', '=', '<', '>', '≤', '≥']
export default (k, operatorFunction, symbol) => (recurse, k, v) => {
let evaluate = (cache, situation, parsedRules, node) => {
const explanation = map(
Expand Down Expand Up @@ -52,20 +54,33 @@ export default (k, operatorFunction, symbol) => (recurse, k, v) => {

let temporalValue = liftTemporal2(
(a, b) => {
if (a === false && ['∕', '-'].includes(node.operator)) {
if (['∕', '-'].includes(node.operator) && a === false) {
return false
}
if (a === false) {
if (['×', '+'].includes(node.operator) && a === false) {
return b
}
if (b === false) {
if (['∕', '-', '×', '+'].includes(node.operator) && b === false) {
return a
}
if (
!['=', '≠'].includes(node.operator) &&
(a === false || b === false)
) {
return false
}
if (
comparisonOperator.includes(node.operator) &&
[a, b].every(value => value.match?.(/[\d]{2}\/[\d]{2}\/[\d]{4}/))
) {
return operatorFunction(convertToDate(a), convertToDate(b))
}
return operatorFunction(a, b)
},
node1.temporalValue ?? pureTemporal(node1.nodeValue),
node2.temporalValue ?? pureTemporal(node2.nodeValue)
)

const nodeValue = temporalAverage(temporalValue, baseNode.unit)

return {
Expand Down
117 changes: 0 additions & 117 deletions source/engine/mecanisms/variations.js

This file was deleted.

152 changes: 152 additions & 0 deletions source/engine/mecanisms/variations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { typeWarning } from 'Engine/error'
import { defaultNode, evaluateNode } from 'Engine/evaluation'
import Variations from 'Engine/mecanismViews/Variations'
import { convertNodeToUnit } from 'Engine/nodeUnits'
import {
liftTemporal2,
mapTemporal,
pureTemporal,
sometime,
temporalAverage
} from 'Engine/period'
import { inferUnit } from 'Engine/units'
import { and, dissoc, not, or } from 'ramda'
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) {
let 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) }
)

// TODO - find an appropriate representation
return {
explanation,
evaluate,
jsx: Variations,
category: 'mecanism',
name: 'variations',
type: 'numeric',
unit: inferUnit(
'+',
explanation.map(r => r.consequence.unit)
)
}
}

export let devariateExplanation = (recurse, mecanismKey, v) => {
let fixedProps = dissoc('variations')(v),
explanation = v.variations.map(({ si, alors, sinon }) => ({
consequence: recurse({
[mecanismKey]: {
...fixedProps,
...(sinon || alors)
}
}),
condition: sinon ? defaultNode(true) : recurse(si)
}))

return explanation
}

function evaluate(
cache,
situationGate,
parsedRules,
node: ReturnType<typeof parse>
) {
const evaluate = evaluateNode.bind(null, cache, situationGate, parsedRules)

const [temporalValue, explanation, unit] = node.explanation.reduce(
(
[evaluation, explanations, unit, previousConditions],
{ condition, consequence },
i: number
) => {
const previousConditionsAlwaysTrue = !sometime(
value => value !== true,
previousConditions
)
if (previousConditionsAlwaysTrue) {
return [
evaluation,
[...explanations, { condition, consequence }],
unit,
previousConditions
]
}
const evaluatedCondition = evaluate(condition)
const currentCondition = liftTemporal2(
and,
mapTemporal(not, previousConditions),
evaluatedCondition.temporalValue ??
pureTemporal(evaluatedCondition.nodeValue)
)
const currentConditionAlwaysFalse = !sometime(Boolean, currentCondition)
if (currentConditionAlwaysFalse) {
return [
evaluation,
[...explanations, { condition: evaluatedCondition, consequence }],
unit,
previousConditions
]
}
let evaluatedConsequence = evaluate(consequence)

try {
evaluatedConsequence = convertNodeToUnit(unit, evaluatedConsequence)
} catch (e) {
return typeWarning(
cache._meta.contexRule,
`L'unité de la branche n° ${i} du mécanisme 'variations' n'est pas compatible avec celle d'une branche précédente`,
e
)
}
const currentValue = liftTemporal2(
(cond, value) => cond && value,
currentCondition,
evaluatedConsequence.temporalValue ??
pureTemporal(evaluatedConsequence.nodeValue)
)

return [
liftTemporal2(or, evaluation, currentValue),
[
...explanations,
{
condition: evaluatedCondition,
consequence: evaluatedConsequence
}
],
unit || evaluatedConsequence.unit,
liftTemporal2(or, previousConditions, currentCondition)
]
},
[pureTemporal(false), [], node.unit, pureTemporal(false)]
)
const nodeValue = temporalAverage(temporalValue, unit)
const missingVariables = mergeAllMissing(
explanation.reduce(
(values, { condition, consequence }) => [
...values,
condition,
consequence
],
[]
)
)
return {
...node,
nodeValue,
unit,
explanation,
missingVariables,
...(temporalValue.length > 1 && { temporalValue })
// TODO
// missingVariables
}
}
9 changes: 9 additions & 0 deletions source/engine/period.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ export function mapTemporal<T1, T2>(
value: fn(value)
}))
}
export function sometime<T1>(
fn: (value: T1) => boolean,
temporalValue: Temporal<T1>
): boolean {
return temporalValue.some(({ start, end, value }) => fn(value))
}

export function liftTemporal2<T1, T2, T3>(
fn: (value1: T1, value2: T2) => T3,
Expand Down Expand Up @@ -342,6 +348,9 @@ export function temporalAverage(
if (!temporalValue.length) {
return false
}
if (temporalValue.length === 1) {
return temporalValue[0].value
}

// La variable est définie sur un interval infini
if (first.start == null || last.end == null) {
Expand Down
2 changes: 1 addition & 1 deletion test/mécanismes/régularisation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ retraite . avec régularisation:
plafond: plafond sécurité sociale
taux: 10%

valeurs annualisée:
valeurs cumulées:
- salaire
- plafond sécurité sociale

Expand Down
Loading

0 comments on commit e06db01

Please sign in to comment.