From 49a7ae2af90885468b9c724674f04e2e5c2ee7fc Mon Sep 17 00:00:00 2001 From: Maxime Quandalle Date: Thu, 20 May 2021 17:42:34 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20Supprime=20l'utilisation=20des?= =?UTF-8?q?=20temporals=20dans=20les=20m=C3=A9canismes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publicodes/core/source/evaluation.ts | 111 ++---------------- publicodes/core/source/mecanisms/barème.ts | 52 +++----- publicodes/core/source/mecanisms/grille.ts | 102 ++++++---------- publicodes/core/source/mecanisms/operation.ts | 58 ++++----- publicodes/core/source/mecanisms/product.ts | 20 ++-- publicodes/core/source/mecanisms/recalcul.ts | 3 - .../core/source/mecanisms/variations.ts | 61 +++------- publicodes/core/source/nodeUnits.ts | 9 -- 8 files changed, 108 insertions(+), 308 deletions(-) diff --git a/publicodes/core/source/evaluation.ts b/publicodes/core/source/evaluation.ts index 447b67c42..ebefa3bd2 100644 --- a/publicodes/core/source/evaluation.ts +++ b/publicodes/core/source/evaluation.ts @@ -7,17 +7,8 @@ import { NodeKind, } from './AST/types' import { warning } from './error' -import { convertNodeToUnit, simplifyNodeUnit } from './nodeUnits' +import { convertNodeToUnit } from './nodeUnits' import parse from './parse' -import { - concatTemporals, - liftTemporalNode, - mapTemporal, - pureTemporal, - Temporal, - temporalAverage, - zipTemporals, -} from './temporal' export const collectNodeMissing = ( node: EvaluatedNode | ASTNode @@ -75,37 +66,17 @@ export const evaluateArray: ( node.explanation.map(evaluate), node.name ) + const values = evaluatedNodes.map(({ nodeValue }) => nodeValue) + const nodeValue = values.some((value) => value === null) + ? null + : values.reduce(reducer, start) - const temporalValues = concatTemporals( - evaluatedNodes.map( - ({ temporalValue, nodeValue }) => - temporalValue ?? pureTemporal(nodeValue) - ) - ) - const temporalValue = mapTemporal((values) => { - if (values.some((value) => value === null)) { - return null - } - return values.reduce(reducer, start) - }, temporalValues) - - const baseEvaluation = { + return { ...node, missingVariables: mergeAllMissing(evaluatedNodes), explanation: evaluatedNodes, ...(evaluatedNodes[0] && { unit: evaluatedNodes[0].unit }), - } - if (temporalValue.length === 1) { - return { - ...baseEvaluation, - nodeValue: temporalValue[0].value, - } - } - - return { - ...baseEvaluation, - temporalValue, - nodeValue: temporalAverage(temporalValue as any), + nodeValue, } } @@ -132,71 +103,3 @@ export const parseObject = (objectShape, value, context) => { }) ) } - -export function evaluateObject( - effet: (this: Engine, explanations: any) => any -) { - return function (node) { - const evaluations = Object.fromEntries( - Object.entries((node as any).explanation).map(([key, value]) => [ - key, - this.evaluate(value as any), - ]) - ) - const temporalExplanations = mapTemporal( - Object.fromEntries, - concatTemporals( - Object.entries(evaluations).map(([key, node]) => - zipTemporals(pureTemporal(key), liftTemporalNode(node as ASTNode)) - ) - ) - ) - const temporalExplanation = mapTemporal((explanations) => { - const evaluation = effet.call(this, explanations) - return { - ...evaluation, - explanation: { - ...explanations, - ...evaluation.explanation, - }, - } - }, temporalExplanations) - - const sameUnitTemporalExplanation: Temporal< - ASTNode & EvaluatedNode & { nodeValue: number } - > = convertNodesToSameUnit - .call( - this, - temporalExplanation.map((x) => x.value), - node.nodeKind - ) - .map((node, i) => ({ - ...temporalExplanation[i], - value: simplifyNodeUnit(node), - })) - - const temporalValue = mapTemporal( - ({ nodeValue }) => nodeValue, - sameUnitTemporalExplanation - ) - const nodeValue = temporalAverage(temporalValue) - const baseEvaluation = { - ...node, - nodeValue, - unit: sameUnitTemporalExplanation[0].value.unit, - explanation: evaluations, - missingVariables: mergeAllMissing(Object.values(evaluations)), - } - if (sameUnitTemporalExplanation.length === 1) { - return { - ...baseEvaluation, - explanation: (sameUnitTemporalExplanation[0] as any).value.explanation, - } - } - return { - ...baseEvaluation, - temporalValue, - temporalExplanation, - } - } as EvaluationFunction -} diff --git a/publicodes/core/source/mecanisms/barème.ts b/publicodes/core/source/mecanisms/barème.ts index 40ba14ff8..087f92bda 100644 --- a/publicodes/core/source/mecanisms/barème.ts +++ b/publicodes/core/source/mecanisms/barème.ts @@ -3,12 +3,6 @@ import { ASTNode } from '../AST/types' import { defaultNode, mergeAllMissing } from '../evaluation' import { registerEvaluationFunction } from '../evaluationFunctions' import parse from '../parse' -import { - liftTemporal2, - liftTemporalNode, - mapTemporal, - temporalAverage, -} from '../temporal' import { convertUnit, parseUnit } from '../units' import { evaluatePlafondUntilActiveTranche, @@ -78,44 +72,28 @@ const evaluate: EvaluationFunction<'barème'> = function (node) { const evaluate = this.evaluate.bind(this) const assiette = this.evaluate(node.explanation.assiette) const multiplicateur = this.evaluate(node.explanation.multiplicateur) - const temporalTranchesPlafond = liftTemporal2( - (assiette, multiplicateur) => - evaluatePlafondUntilActiveTranche.call(this, { - parsedTranches: node.explanation.tranches, - assiette, - multiplicateur, - }), - liftTemporalNode(assiette as any), - liftTemporalNode(multiplicateur as any) + const tranches = evaluateBarème( + evaluatePlafondUntilActiveTranche.call(this, { + parsedTranches: node.explanation.tranches, + assiette, + multiplicateur, + }), + assiette, + evaluate ) - const temporalTranches = liftTemporal2( - (tranches, assiette) => evaluateBarème(tranches, assiette, evaluate), - temporalTranchesPlafond, - liftTemporalNode(assiette as any) - ) - const temporalValue = mapTemporal( - (tranches) => - tranches.reduce( - (value, { nodeValue }) => - nodeValue == null ? null : value + nodeValue, - 0 - ), - temporalTranches + const nodeValue = tranches.reduce( + (value, { nodeValue }) => (nodeValue == null ? null : value + nodeValue), + 0 ) + return { ...node, - nodeValue: temporalAverage(temporalValue), - ...(temporalValue.length > 1 - ? { - temporalValue, - } - : { missingVariables: mergeAllMissing(temporalTranches[0].value) }), + nodeValue, + missingVariables: mergeAllMissing(tranches), explanation: { assiette, multiplicateur, - ...(temporalTranches.length > 1 - ? { temporalTranches } - : { tranches: temporalTranches[0].value }), + tranches, }, unit: assiette.unit, } as any diff --git a/publicodes/core/source/mecanisms/grille.ts b/publicodes/core/source/mecanisms/grille.ts index b7f5633df..05763dd95 100644 --- a/publicodes/core/source/mecanisms/grille.ts +++ b/publicodes/core/source/mecanisms/grille.ts @@ -3,12 +3,6 @@ import { ASTNode } from '../AST/types' import { defaultNode, mergeAllMissing } from '../evaluation' import { registerEvaluationFunction } from '../evaluationFunctions' import parse from '../parse' -import { - liftTemporal2, - liftTemporalNode, - mapTemporal, - temporalAverage, -} from '../temporal' import { evaluatePlafondUntilActiveTranche, parseTranches, @@ -37,78 +31,58 @@ export default function parseGrille(v, context): GrilleNode { nodeKind: 'grille', } } -const evaluateGrille = (tranches, evaluate) => - tranches.map((tranche) => { - if (tranche.isActive === false) { - return tranche - } - const montant = evaluate(tranche.montant) - return { - ...tranche, - montant, - nodeValue: montant.nodeValue, - unit: montant.unit, - missingVariables: mergeAllMissing([montant, tranche]), - } - }) const evaluate: EvaluationFunction<'grille'> = function (node) { const evaluate = this.evaluate.bind(this) const assiette = this.evaluate(node.explanation.assiette) const multiplicateur = this.evaluate(node.explanation.multiplicateur) - const temporalTranchesPlafond = liftTemporal2( - (assiette, multiplicateur) => - evaluatePlafondUntilActiveTranche.call(this, { - parsedTranches: node.explanation.tranches, - assiette, - multiplicateur, - }), - liftTemporalNode(assiette as any), - liftTemporalNode(multiplicateur as any) - ) - const temporalTranches = mapTemporal( - (tranches) => evaluateGrille(tranches, evaluate), - temporalTranchesPlafond - ) + const tranches = evaluatePlafondUntilActiveTranche + .call(this, { + parsedTranches: node.explanation.tranches, + assiette, + multiplicateur, + }) + .map((tranche) => { + if (tranche.isActive === false) { + return tranche + } + const montant = evaluate(tranche.montant) + return { + ...tranche, + montant, + nodeValue: montant.nodeValue, + unit: montant.unit, + missingVariables: mergeAllMissing([montant, tranche]), + } + }) - const activeTranches = mapTemporal((tranches) => { - const activeTranche = tranches.find((tranche) => tranche.isActive) - if (activeTranche) { - return [activeTranche] - } - const lastTranche = tranches[tranches.length - 1] - if (lastTranche.isAfterActive === false) { - return [{ nodeValue: false }] - } - return tranches.filter((tranche) => tranche.isActive === null) - }, temporalTranches) - const temporalValue = mapTemporal( - (tranches) => - !tranches[0] - ? false - : tranches[0].isActive === null - ? null - : tranches[0].nodeValue, - activeTranches - ) + let activeTranches + const activeTranche = tranches.find((tranche) => tranche.isActive) + if (activeTranche) { + activeTranches = [activeTranche] + } else if (tranches[tranches.length - 1].isAfterActive === false) { + activeTranches = [{ nodeValue: false }] + } else { + activeTranches = tranches.filter((tranche) => tranche.isActive === null) + } + + const nodeValue = !activeTranches[0] + ? false + : activeTranches[0].isActive === null + ? null + : activeTranches[0].nodeValue return { ...node, - nodeValue: temporalAverage(temporalValue), - ...(temporalValue.length > 1 - ? { - temporalValue, - } - : { missingVariables: mergeAllMissing(activeTranches[0].value) }), + nodeValue, + missingVariables: mergeAllMissing(activeTranches), explanation: { ...node.explanation, assiette, multiplicateur, - ...(temporalTranches.length > 1 - ? { temporalTranches } - : { tranches: temporalTranches[0].value }), + tranches, }, - unit: activeTranches[0]?.value[0]?.unit ?? undefined, + unit: activeTranches[0]?.unit ?? undefined, } as any } diff --git a/publicodes/core/source/mecanisms/operation.ts b/publicodes/core/source/mecanisms/operation.ts index f093548b0..d7b2b69fd 100644 --- a/publicodes/core/source/mecanisms/operation.ts +++ b/publicodes/core/source/mecanisms/operation.ts @@ -1,13 +1,11 @@ import { EvaluationFunction } from '..' -import { ASTNode } from '../AST/types' +import { ASTNode, EvaluatedNode } from '../AST/types' import { convertToDate } from '../date' import { warning } from '../error' import { mergeAllMissing } from '../evaluation' import { registerEvaluationFunction } from '../evaluationFunctions' import { convertNodeToUnit } from '../nodeUnits' import parse from '../parse' -import { liftTemporal2, pureTemporal, temporalAverage } from '../temporal' -import { EvaluatedNode } from '../AST/types' import { inferUnit, serializeUnit } from '../units' const knownOperations = { @@ -74,7 +72,26 @@ const evaluate: EvaluationFunction<'operation'> = function (node) { ) } } - const baseNode = { + + const operatorFunction = knownOperations[node.operationKind][0] + + const a = node1.nodeValue as string | false + const b = node2.nodeValue as string | false + + const nodeValue = + !['≠', '='].includes(node.operator) && a === false && b === false + ? false + : ['<', '>', '≤', '≥', '∕', '×'].includes(node.operator) && + (a === false || b === false) + ? false + : a !== false && + b !== false && + ['≠', '=', '<', '>', '≤', '≥'].includes(node.operator) && + [a, b].every((value) => value.match?.(/[\d]{2}\/[\d]{2}\/[\d]{4}/)) + ? operatorFunction(convertToDate(a), convertToDate(b)) + : operatorFunction(a, b) + + return { ...node, explanation, ...((node.operationKind === '*' || @@ -84,40 +101,7 @@ const evaluate: EvaluationFunction<'operation'> = function (node) { unit: inferUnit(node.operationKind, [node1.unit, node2.unit]), }), missingVariables, - } - - const operatorFunction = knownOperations[node.operationKind][0] - - const temporalValue = liftTemporal2( - (a: string | false, b: string | false) => { - if (!['≠', '='].includes(node.operator) && a === false && b === false) { - return false - } - if ( - ['<', '>', '≤', '≥', '∕', '×'].includes(node.operator) && - (a === false || b === false) - ) { - return false - } - if ( - a !== false && - b !== false && - ['≠', '=', '<', '>', '≤', '≥'].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) as any), - node2.temporalValue ?? (pureTemporal(node2.nodeValue) as any) - ) - const nodeValue = temporalAverage(temporalValue, baseNode.unit) - - return { - ...baseNode, nodeValue, - ...(temporalValue.length > 1 && { temporalValue }), } } diff --git a/publicodes/core/source/mecanisms/product.ts b/publicodes/core/source/mecanisms/product.ts index 612df9b95..f56195126 100644 --- a/publicodes/core/source/mecanisms/product.ts +++ b/publicodes/core/source/mecanisms/product.ts @@ -1,7 +1,7 @@ import { EvaluationFunction } from '..' import { ASTNode } from '../AST/types' import { warning } from '../error' -import { defaultNode, evaluateObject, parseObject } from '../evaluation' +import { defaultNode, parseObject } from '../evaluation' import { registerEvaluationFunction } from '../evaluationFunctions' import { convertNodeToUnit, simplifyNodeUnit } from '../nodeUnits' import { areUnitConvertible, convertUnit, inferUnit } from '../units' @@ -32,12 +32,12 @@ export const mecanismProduct = (v, context) => { } as ProductNode } -const productEffect: EvaluationFunction = function ({ - assiette, - taux, - facteur, - plafond, -}: any) { +const evaluateProduit: EvaluationFunction<'produit'> = function (node) { + const assiette = this.evaluate(node.explanation.assiette) + const taux = this.evaluate(node.explanation.taux) + const facteur = this.evaluate(node.explanation.facteur) + let plafond = this.evaluate(node.explanation.plafond) + if (assiette.unit) { try { plafond = convertNodeToUnit(assiette.unit, plafond) @@ -77,11 +77,9 @@ const productEffect: EvaluationFunction = function ({ unit, explanation: { - plafondActif: assiette.nodeValue > plafond.nodeValue, + plafondActif: (assiette.nodeValue as any) > (plafond as any).nodeValue, }, }) } -const evaluate = evaluateObject<'produit'>(productEffect) - -registerEvaluationFunction('produit', evaluate) +registerEvaluationFunction('produit', evaluateProduit) diff --git a/publicodes/core/source/mecanisms/recalcul.ts b/publicodes/core/source/mecanisms/recalcul.ts index f9eb7e1ca..8db2f9423 100644 --- a/publicodes/core/source/mecanisms/recalcul.ts +++ b/publicodes/core/source/mecanisms/recalcul.ts @@ -62,9 +62,6 @@ const evaluateRecalcul: EvaluationFunction<'recalcul'> = function (node) { }, missingVariables: evaluatedNode.missingVariables, ...('unit' in evaluatedNode && { unit: evaluatedNode.unit }), - ...(evaluatedNode.temporalValue && { - temporalValue: evaluatedNode.temporalValue, - }), } } diff --git a/publicodes/core/source/mecanisms/variations.ts b/publicodes/core/source/mecanisms/variations.ts index 1c8c3b9c0..845b9dd1a 100644 --- a/publicodes/core/source/mecanisms/variations.ts +++ b/publicodes/core/source/mecanisms/variations.ts @@ -1,17 +1,10 @@ import { EvaluationFunction } from '..' -import { ASTNode, Unit } from '../AST/types' +import { ASTNode, EvaluatedNode, Unit } from '../AST/types' import { warning } from '../error' import { bonus, defaultNode, mergeAllMissing } from '../evaluation' import { registerEvaluationFunction } from '../evaluationFunctions' import { convertNodeToUnit } from '../nodeUnits' import parse from '../parse' -import { - liftTemporal2, - pureTemporal, - sometime, - Temporal, - temporalAverage, -} from '../temporal' export type VariationNode = { explanation: Array<{ @@ -62,12 +55,12 @@ export default function parseVariations(v, context): VariationNode { } const evaluate: EvaluationFunction<'variations'> = function (node) { - const [temporalValue, explanation, unit] = node.explanation.reduce< + const [nodeValue, explanation, unit] = node.explanation.reduce< [ - Temporal, + EvaluatedNode['nodeValue'], VariationNode['explanation'], Unit | undefined, - Temporal + boolean | null ] >( ( @@ -75,11 +68,7 @@ const evaluate: EvaluationFunction<'variations'> = function (node) { { condition, consequence }, i: number ) => { - const previousConditionsAlwaysTrue = !sometime( - (value) => value !== true, - previousConditions - ) - if (previousConditionsAlwaysTrue) { + if (previousConditions === true) { return [ evaluation, [...explanations, { condition, consequence }], @@ -88,24 +77,19 @@ const evaluate: EvaluationFunction<'variations'> = function (node) { ] } const evaluatedCondition = this.evaluate(condition) - const currentCondition = liftTemporal2( - (previousCond, currentCond) => - previousCond === null - ? previousCond - : !previousCond && - (currentCond === null ? null : currentCond !== false), - previousConditions, - evaluatedCondition.temporalValue ?? - pureTemporal(evaluatedCondition.nodeValue) - ) + const currentCondition = + previousConditions === null + ? previousConditions + : !previousConditions && + (evaluatedCondition.nodeValue === null + ? null + : evaluatedCondition.nodeValue !== false) + evaluatedCondition.missingVariables = bonus( evaluatedCondition.missingVariables ) - const currentConditionAlwaysFalse = !sometime( - (x) => x !== false, - currentCondition - ) - if (currentConditionAlwaysFalse) { + + if (currentCondition === false) { return [ evaluation, [...explanations, { condition: evaluatedCondition, consequence }], @@ -128,15 +112,8 @@ const evaluate: EvaluationFunction<'variations'> = function (node) { ) } } - const currentValue = liftTemporal2( - (cond, value) => cond && value, - currentCondition, - evaluatedConsequence.temporalValue ?? - pureTemporal(evaluatedConsequence.nodeValue) - ) - const or = (a, b) => a || b return [ - liftTemporal2(or, evaluation, currentValue), + currentCondition && evaluatedConsequence.nodeValue, [ ...explanations, { @@ -146,13 +123,12 @@ const evaluate: EvaluationFunction<'variations'> = function (node) { }, ], unit || evaluatedConsequence.unit, - liftTemporal2(or, previousConditions, currentCondition), + previousConditions || currentCondition, ] }, - [pureTemporal(false), [], undefined, pureTemporal(false)] + [false, [], undefined, false] ) - const nodeValue = temporalAverage(temporalValue, unit) const missingVariables = mergeAllMissing( explanation.reduce( (values, { condition, consequence }) => [ @@ -170,7 +146,6 @@ const evaluate: EvaluationFunction<'variations'> = function (node) { ...(unit !== undefined && { unit }), explanation, missingVariables, - ...(temporalValue.length > 1 && { temporalValue }), } } diff --git a/publicodes/core/source/nodeUnits.ts b/publicodes/core/source/nodeUnits.ts index 504ae21e3..fc2eeb369 100644 --- a/publicodes/core/source/nodeUnits.ts +++ b/publicodes/core/source/nodeUnits.ts @@ -1,5 +1,4 @@ import { EvaluatedNode, Unit } from './AST/types' -import { mapTemporal } from './temporal' import { convertUnit, simplifyUnit } from './units' export function simplifyNodeUnit(node) { @@ -15,20 +14,12 @@ export function convertNodeToUnit( to: Unit | undefined, node: Node ): Node { - const temporalValue = - node.temporalValue && node.unit - ? mapTemporal( - (value) => convertUnit(node.unit, to, value as number), - node.temporalValue - ) - : node.temporalValue return { ...node, nodeValue: node.unit && typeof node.nodeValue === 'number' ? convertUnit(node.unit, to, node.nodeValue) : node.nodeValue, - ...(temporalValue && { temporalValue }), unit: to, } }