diff --git a/mon-entreprise/source/sites/mon-entreprise.fr/middlewares/trackSimulatorActions.ts b/mon-entreprise/source/sites/mon-entreprise.fr/middlewares/trackSimulatorActions.ts index df1e9e963..5039f2f38 100644 --- a/mon-entreprise/source/sites/mon-entreprise.fr/middlewares/trackSimulatorActions.ts +++ b/mon-entreprise/source/sites/mon-entreprise.fr/middlewares/trackSimulatorActions.ts @@ -7,14 +7,13 @@ export default (tracker: Tracker) => { next(action) const newState = getState() if (action.type == 'STEP_ACTION' && action.name == 'fold') { - tracker.debouncedPush([ - 'trackEvent', - 'Simulator::answer', - action.source, - action.step, - situationSelector(newState)[action.step as DottedName], - ]) - + // tracker.debouncedPush([ + // 'trackEvent', + // 'Simulator::answer', + // action.source, + // action.step, + // situationSelector(newState)[action.step as DottedName], + // ]) // TODO : add tracking in UI instead ? // if (!currentQuestionSelector(newState)) { // tracker.push([ diff --git a/publicodes/source/components/Explanation.tsx b/publicodes/source/components/Explanation.tsx index c1a6ab729..283e3eec9 100644 --- a/publicodes/source/components/Explanation.tsx +++ b/publicodes/source/components/Explanation.tsx @@ -28,6 +28,9 @@ import UneDeCesConditions from './mecanisms/UneDeCesConditions' import UnePossibilité from './mecanisms/UnePossibilité' import Unité from './mecanisms/Unité' import Variations from './mecanisms/Variations' +import { useContext } from 'react' +import { EngineContext } from './contexts' +import { InternalError } from '../error' const UIComponents = { constant: ConstantNode, @@ -66,9 +69,19 @@ const UIComponents = { export default function Explanation({ node }) { const visualisationKind = node.visualisationKind || node.nodeKind + const engine = useContext(EngineContext) + if (!engine) { + throw new InternalError(node) + } + + // On ne veut pas (pour l'instant) déclencher une évaluation juste pour + // l'affichage. + // A voir si cela doit évoluer... + const displayedNode = node.evaluationId ? engine.evaluateNode(node) : node + const Component = UIComponents[visualisationKind] if (!Component) { throw new Error(`Unknown visualisation: ${visualisationKind}`) } - return + return } diff --git a/publicodes/source/components/mecanisms/common.tsx b/publicodes/source/components/mecanisms/common.tsx index 3ccb15fd1..b36f36381 100644 --- a/publicodes/source/components/mecanisms/common.tsx +++ b/publicodes/source/components/mecanisms/common.tsx @@ -289,19 +289,7 @@ export function Leaf( !node.name.includes(' . ') && rule.virtualRule ) { - return ( - - ) + return } return (
({ _meta: { contextRule: [] }, + nodes: new Map(), }) type Cache = { @@ -31,6 +32,7 @@ type Cache = { inRecalcul?: boolean filter?: string } + nodes: Map } export type EvaluationOptions = Partial<{ @@ -60,16 +62,10 @@ export default class Engine { parsedRules: ParsedRules parsedSituation: Record = {} replacements: Record> = {} - cache: Cache - - // A number that is incremented every time the situation changes, and is used - // for inline cache invalidation. - situationVersion = 0 + cache: Cache = emptyCache() private warnings: Array = [] constructor(rules: string | Record | ParsedRules) { - this.cache = emptyCache() - this.resetCache() if (typeof rules === 'string') { this.parsedRules = parsePublicodes(rules) as ParsedRules } @@ -88,7 +84,7 @@ export default class Engine { this.replacements = getReplacements(this.parsedRules) } - private resetCache() { + resetCache() { this.cache = emptyCache() } @@ -96,7 +92,6 @@ export default class Engine { situation: Partial> = {} ) { this.resetCache() - this.situationVersion++ this.parsedSituation = mapObjIndexed((value, key) => { if (value && typeof value === 'object' && 'nodeKind' in value) { return value as ASTNode @@ -153,20 +148,19 @@ export default class Engine { } evaluateNode( - node: N & { lastEvaluation?: number; res?: EvaluatedNode } + node: N & { evaluationId?: string } ): N & EvaluatedNode { if (!node.nodeKind) { throw Error('The provided node must have a "nodeKind" attribute') } else if (!evaluationFunctions[node.nodeKind]) { throw Error(`Unknown "nodeKind": ${node.nodeKind}`) } - - if (!node.res || node.lastEvaluation !== this.situationVersion) { - node.res = evaluationFunctions[node.nodeKind].call(this, node) - node.lastEvaluation = this.situationVersion + let result = this.cache.nodes.get(node) + if (result === undefined) { + result = evaluationFunctions[node.nodeKind].call(this, node) } - - return node.res! + this.cache.nodes.set(node, result!) + return result as N & EvaluatedNode } } diff --git a/publicodes/source/mecanisms/inversion.ts b/publicodes/source/mecanisms/inversion.ts index 092968b7c..9c200211f 100644 --- a/publicodes/source/mecanisms/inversion.ts +++ b/publicodes/source/mecanisms/inversion.ts @@ -55,16 +55,15 @@ export const evaluateInversion: EvaluationFunction<'inversion'> = function ( const evaluatedInversionGoal = this.evaluateNode(inversionGoal) const unit = 'unit' in node ? node.unit : evaluatedInversionGoal.unit - const originalCache = { ...this.cache } + const originalCache = this.cache const originalSituation = { ...this.parsedSituation } let inversionNumberOfIterations = 0 delete this.parsedSituation[inversionGoal.dottedName as string] const evaluateWithValue = (n: number) => { inversionNumberOfIterations++ - this.cache = { - _meta: { ...originalCache._meta }, - } - this.situationVersion++ + this.resetCache() + this.cache._meta = { ...originalCache._meta } + this.parsedSituation[node.explanation.ruleToInverse] = { unit: unit, nodeKind: 'unité', @@ -141,7 +140,6 @@ export const evaluateInversion: EvaluationFunction<'inversion'> = function ( // // Uncomment to display the two attempts and their result // console.table([{ x: x1, y: y1 }, { x: x2, y: y2 }]) // console.log('iteration:', inversionNumberOfIterations) - this.situationVersion++ this.cache = originalCache this.parsedSituation = originalSituation return { diff --git a/publicodes/source/mecanisms/recalcul.ts b/publicodes/source/mecanisms/recalcul.ts index 74ff0ddcc..cafa9bcf4 100644 --- a/publicodes/source/mecanisms/recalcul.ts +++ b/publicodes/source/mecanisms/recalcul.ts @@ -32,13 +32,13 @@ const evaluateRecalcul: EvaluationFunction<'recalcul'> = function (node) { serializeUnit(originRule.unit) !== serializeUnit(replacement.unit) ) as Array<[ReferenceNode & EvaluatedNode, EvaluatedNode]> - const originalCache = { ...this.cache } + const originalCache = this.cache const originalSituation = { ...this.parsedSituation } // Optimisation : no need for recalcul if situation is the same const invalidateCache = Object.keys(amendedSituation).length > 0 if (invalidateCache) { - this.cache = { _meta: { ...this.cache._meta, inRecalcul: true } } - this.situationVersion++ + this.resetCache() + this.cache._meta = { ...this.cache._meta, inRecalcul: true } } this.parsedSituation = { @@ -59,7 +59,6 @@ const evaluateRecalcul: EvaluationFunction<'recalcul'> = function (node) { this.parsedSituation = originalSituation if (invalidateCache) { this.cache = originalCache - this.situationVersion++ } return { ...node,