⚙️ Adapation du moteur à la simulation multiple
parent
73ed97d647
commit
92fed2c520
|
@ -8,13 +8,13 @@ import { withRouter } from 'react-router'
|
|||
import './Results.css'
|
||||
import {clearDict} from 'Engine/traverse'
|
||||
import {encodeRuleName} from 'Engine/rules'
|
||||
import {getObjectives} from 'Engine/generateQuestions'
|
||||
import RuleValueVignette from './rule/RuleValueVignette'
|
||||
|
||||
@withRouter
|
||||
@connect(
|
||||
state => ({
|
||||
analysedSituation: state.analysedSituation,
|
||||
analysis: state.analysis,
|
||||
targetName: state.targetName,
|
||||
conversationStarted: !R.isEmpty(state.form),
|
||||
conversationFirstAnswer: R.path(['form', 'conversation', 'values'])(state),
|
||||
situationGate: state.situationGate
|
||||
|
@ -23,37 +23,39 @@ import RuleValueVignette from './rule/RuleValueVignette'
|
|||
export default class Results extends Component {
|
||||
componentDidMount(){
|
||||
setTimeout(() =>
|
||||
this.props.setElementHeight(this.el.offsetHeight)
|
||||
, 1)
|
||||
this.el && this.props.setElementHeight(this.el.offsetHeight)
|
||||
, 1)
|
||||
}
|
||||
render() {
|
||||
let {
|
||||
analysedSituation,
|
||||
analysis,
|
||||
targetName,
|
||||
conversationStarted,
|
||||
conversationFirstAnswer: showResults,
|
||||
situationGate,
|
||||
location
|
||||
} = this.props
|
||||
|
||||
let explanation = R.has('root', analysedSituation) && clearDict() && getObjectives(situationGate, analysedSituation.root, analysedSituation.parsedRules)
|
||||
if (!analysis) return null
|
||||
|
||||
if (!explanation) return null
|
||||
let {targets} = analysis
|
||||
|
||||
clearDict() // pourquoi ??
|
||||
|
||||
let onRulePage = R.contains('/regle/')(location.pathname)
|
||||
return (
|
||||
<section ref={el => this.el = el} id="results" className={classNames({show: showResults})}>
|
||||
{onRulePage && conversationStarted ?
|
||||
<div id ="results-actions">
|
||||
<Link id="toSimulation" to={"/simu/" + encodeRuleName(analysedSituation.root.name)}>
|
||||
<Link id="toSimulation" to={'/simu/' + encodeRuleName(targetName)}>
|
||||
<i className="fa fa-arrow-circle-left" aria-hidden="true"></i>Reprendre la simulation
|
||||
</Link>
|
||||
</div>
|
||||
: <div id="results-titles">
|
||||
<h2><i className="fa fa-calculator" aria-hidden="true"></i>{explanation.length == 1 ? 'Votre résultat' : 'Vos résultats'}<span>·</span><small>Cliquez pour comprendre chaque calcul</small></h2>
|
||||
<h2><i className="fa fa-calculator" aria-hidden="true"></i>{targets.length == 1 ? 'Votre résultat' : 'Vos résultats'}<span>·</span><small>Cliquez pour comprendre chaque calcul</small></h2>
|
||||
</div>
|
||||
}
|
||||
<ul>
|
||||
{explanation.map( rule => <li key={rule.nom}>
|
||||
{targets.map( rule => <li key={rule.nom}>
|
||||
<RuleValueVignette {...rule} conversationStarted={conversationStarted} />
|
||||
</li>)}
|
||||
</ul>
|
||||
|
|
|
@ -24,11 +24,10 @@ import ReactPiwik from './Tracker'
|
|||
foldedSteps: state.foldedSteps,
|
||||
extraSteps: state.extraSteps,
|
||||
themeColours: state.themeColours,
|
||||
analysedSituation: state.analysedSituation,
|
||||
situationGate: state.situationGate,
|
||||
}),
|
||||
dispatch => ({
|
||||
startConversation: rootVariable => dispatch({type: START_CONVERSATION, rootVariable}),
|
||||
startConversation: targetName => dispatch({type: START_CONVERSATION, targetName}),
|
||||
resetForm: () => dispatch(reset('conversation'))
|
||||
})
|
||||
)
|
||||
|
@ -56,7 +55,8 @@ export default class extends Component {
|
|||
this.props.startConversation(name)
|
||||
}
|
||||
render(){
|
||||
if (!this.rule.formule) return <Redirect to={"/regle/" + this.name}/>
|
||||
if (!this.rule.formule && !R.path(['simulateur', 'objectifs'], this.rule))
|
||||
return <Redirect to={'/regle/' + this.name} />
|
||||
|
||||
let
|
||||
{started} = this.state,
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
rules,
|
||||
disambiguateRuleReference
|
||||
} from "Engine/rules.js"
|
||||
import { analyseSituation } from "Engine/traverse"
|
||||
import { analyse } from "Engine/traverse"
|
||||
import "./Examples.css"
|
||||
|
||||
export default class Examples extends Component {
|
||||
|
@ -23,10 +23,10 @@ export default class Examples extends Component {
|
|||
R.fromPairs
|
||||
)(ex.situation)
|
||||
|
||||
let runExemple = analyseSituation(rules, rule.name)(
|
||||
let runExemple = analyse(rules, rule.name)(
|
||||
v => exempleSituation[v]
|
||||
),
|
||||
exempleValue = runExemple.nodeValue
|
||||
exempleValue = runExemple.targets[0].nodeValue
|
||||
|
||||
return {
|
||||
...ex,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { connect } from "react-redux"
|
|||
import R from "ramda"
|
||||
import "./Rule.css"
|
||||
import { rules, decodeRuleName, nameLeaf } from "Engine/rules.js"
|
||||
import { analyseSituation } from "Engine/traverse"
|
||||
import { analyse } from "Engine/traverse"
|
||||
import { START_CONVERSATION } from "../../actions"
|
||||
import possiblesDestinataires from "Règles/ressources/destinataires/destinataires.yaml"
|
||||
import { capitalise0 } from "../../utils"
|
||||
|
@ -19,8 +19,8 @@ import {createMarkdownDiv} from 'Engine/marked'
|
|||
form: state.form
|
||||
}),
|
||||
dispatch => ({
|
||||
startConversation: rootVariable =>
|
||||
dispatch({ type: START_CONVERSATION, rootVariable })
|
||||
startConversation: targetName =>
|
||||
dispatch({ type: START_CONVERSATION, targetName })
|
||||
})
|
||||
)
|
||||
export default class Rule extends Component {
|
||||
|
@ -36,9 +36,9 @@ export default class Rule extends Component {
|
|||
}
|
||||
}
|
||||
setRule(name) {
|
||||
this.rule = analyseSituation(rules, nameLeaf(decodeRuleName(name)))(
|
||||
this.rule = analyse(rules, nameLeaf(decodeRuleName(name)))(
|
||||
this.props.situationGate
|
||||
)
|
||||
).targets[0]
|
||||
}
|
||||
componentWillMount() {
|
||||
let { match: { params: { name } } } = this.props
|
||||
|
|
|
@ -8,9 +8,9 @@ import Select from 'Components/conversation/select/Select'
|
|||
import SelectAtmp from 'Components/conversation/select/SelectTauxRisque'
|
||||
import formValueTypes from 'Components/conversation/formValueTypes'
|
||||
|
||||
import {findInversion} from './traverse'
|
||||
import {findRuleByDottedName} from './rules'
|
||||
import {collectNodeMissing, evaluateNode} from './evaluation'
|
||||
import {collectNodeMissing} from './evaluation'
|
||||
|
||||
|
||||
/*
|
||||
COLLECTE DES VARIABLES MANQUANTES
|
||||
|
@ -27,33 +27,8 @@ import {collectNodeMissing, evaluateNode} from './evaluation'
|
|||
missingVariables: {variable: [objectives]}
|
||||
*/
|
||||
|
||||
// On peut travailler sur une somme, les objectifs sont alors les variables de cette somme.
|
||||
// Ou sur une variable unique ayant une formule ou une conodition 'non applicable si', elle est elle-même le seul objectif
|
||||
export let getObjectives = (situationGate, root, parsedRules) => {
|
||||
let formuleType = R.path(["formule", "explanation", "name"])(root)
|
||||
|
||||
let targets = formuleType == "somme"
|
||||
? R.pluck(
|
||||
"dottedName",
|
||||
R.path(["formule", "explanation", "explanation"])(root)
|
||||
)
|
||||
: (root.formule || root['non applicable si'] || root['applicable si']) ? [root.dottedName] : null,
|
||||
names = targets ? R.reject(R.isNil)(targets) : []
|
||||
|
||||
let inversion = findInversion(situationGate, parsedRules, root)
|
||||
|
||||
if (inversion){
|
||||
return [evaluateNode(situationGate, parsedRules, inversion.fixedObjectiveRule)]
|
||||
}
|
||||
|
||||
let findAndEvaluate = name => evaluateNode(situationGate,parsedRules,findRuleByDottedName(parsedRules,name))
|
||||
|
||||
return R.map(findAndEvaluate,names)
|
||||
}
|
||||
|
||||
export let collectMissingVariables = (groupMethod='groupByMissingVariable') => (situationGate, {root, parsedRules}) => {
|
||||
return R.pipe(
|
||||
R.curry(getObjectives)(situationGate),
|
||||
export let collectMissingVariables = targets =>
|
||||
R.pipe(
|
||||
R.chain( v =>
|
||||
R.pipe(
|
||||
collectNodeMissing,
|
||||
|
@ -62,17 +37,17 @@ export let collectMissingVariables = (groupMethod='groupByMissingVariable') => (
|
|||
)(v)
|
||||
),
|
||||
//groupBy missing variable but remove mv from value, it's now in the key
|
||||
R.groupBy(groupMethod == 'groupByMissingVariable' ? R.last : R.head),
|
||||
R.map(R.map(groupMethod == 'groupByMissingVariable' ? R.head : R.last))
|
||||
R.groupBy(R.last),
|
||||
R.map(R.map(R.head))
|
||||
// below is a hand implementation of above... function composition can be nice sometimes :')
|
||||
// R.reduce( (memo, [mv, dependencyOf]) => ({...memo, [mv]: [...(memo[mv] || []), dependencyOf] }), {})
|
||||
)(root, parsedRules)
|
||||
}
|
||||
)(targets)
|
||||
|
||||
export let nextSteps = (situationGate, flatRules, analysedSituation) => {
|
||||
|
||||
export let nextSteps = (situationGate, flatRules, analysis) => {
|
||||
let impact = ([variable, objectives]) => R.length(objectives)
|
||||
|
||||
let missingVariables = collectMissingVariables('groupByMissingVariable')(situationGate, analysedSituation),
|
||||
let missingVariables = collectMissingVariables(analysis.targets),
|
||||
pairs = R.toPairs(missingVariables),
|
||||
sortedPairs = R.sort(R.descend(impact), pairs)
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ let fillVariableNode = (rules, rule) => parseResult => {
|
|||
variablePartialName = fragments.join(' . '),
|
||||
dottedName = disambiguateRuleReference(rules, rule, variablePartialName)
|
||||
|
||||
let jsx = (nodeValue) => (
|
||||
let jsx = nodeValue => (
|
||||
<Leaf classes="variable" name={fragments.join(' . ')} value={nodeValue} />
|
||||
)
|
||||
|
||||
|
@ -353,7 +353,8 @@ let treat = (rules, rule) => rawNode => {
|
|||
let mecanisms = R.intersection(R.keys(rawNode), R.keys(knownMecanisms))
|
||||
|
||||
if (mecanisms.length != 1) {
|
||||
console.log( // eslint-disable-line no-console
|
||||
console.log(
|
||||
// eslint-disable-line no-console
|
||||
'Erreur : On ne devrait reconnaître que un et un seul mécanisme dans cet objet',
|
||||
mecanisms,
|
||||
rawNode
|
||||
|
@ -424,17 +425,16 @@ export let findInversion = (situationGate, rules, rule) => {
|
|||
}
|
||||
|
||||
export let treatRuleRoot = (rules, rule) => {
|
||||
|
||||
let evaluate = (situationGate, parsedRules, r) => {
|
||||
let inversion = findInversion(situationGate, parsedRules, r)
|
||||
if (inversion) {
|
||||
let {fixedObjectiveValue, fixedObjectiveRule} = inversion
|
||||
let
|
||||
fx = x => evaluateNode(
|
||||
n => (r.name === n || n === 'sys.filter') ? x : situationGate(n), //TODO pourquoi doit-on nous préoccuper de sys.filter ?
|
||||
parsedRules,
|
||||
fixedObjectiveRule
|
||||
).nodeValue,
|
||||
let { fixedObjectiveValue, fixedObjectiveRule } = inversion
|
||||
let fx = x =>
|
||||
evaluateNode(
|
||||
n => (r.name === n || n === 'sys.filter' ? x : situationGate(n)), //TODO pourquoi doit-on nous préoccuper de sys.filter ?
|
||||
parsedRules,
|
||||
fixedObjectiveRule
|
||||
).nodeValue,
|
||||
tolerancePercentage = 0.00001,
|
||||
// cette fonction détermine la racine d'une fonction sans faire trop d'itérations
|
||||
nodeValue = uniroot(
|
||||
|
@ -445,18 +445,23 @@ export let treatRuleRoot = (rules, rule) => {
|
|||
100
|
||||
)
|
||||
|
||||
// si fx renvoie null pour une valeur numérique standard, disons 1000, on peut
|
||||
// considérer que l'inversion est impossible du fait de variables manquantes
|
||||
// TODO fx peut être null pour certains x, et valide pour d'autres : on peut implémenter ici le court-circuit
|
||||
return fx(1000) == null ? {
|
||||
...r,
|
||||
nodeValue: null,
|
||||
inversionMissingVariables: collectNodeMissing(evaluateNode(
|
||||
n => (r.name === n || n === 'sys.filter') ? 1000 : situationGate(n), //TODO pourquoi doit-on nous préoccuper de sys.filter ?
|
||||
parsedRules,
|
||||
fixedObjectiveRule
|
||||
))
|
||||
} : {...r, nodeValue}
|
||||
// si fx renvoie null pour une valeur numérique standard, disons 1000, on peut
|
||||
// considérer que l'inversion est impossible du fait de variables manquantes
|
||||
// TODO fx peut être null pour certains x, et valide pour d'autres : on peut implémenter ici le court-circuit
|
||||
return fx(1000) == null
|
||||
? {
|
||||
...r,
|
||||
nodeValue: null,
|
||||
inversionMissingVariables: collectNodeMissing(
|
||||
evaluateNode(
|
||||
n =>
|
||||
r.name === n || n === 'sys.filter' ? 1000 : situationGate(n), //TODO pourquoi doit-on nous préoccuper de sys.filter ?
|
||||
parsedRules,
|
||||
fixedObjectiveRule
|
||||
)
|
||||
)
|
||||
}
|
||||
: { ...r, nodeValue }
|
||||
}
|
||||
|
||||
let evolveRule = R.curry(evaluateNode)(situationGate, parsedRules),
|
||||
|
@ -485,7 +490,7 @@ export let treatRuleRoot = (rules, rule) => {
|
|||
return { ...evaluated, nodeValue, isApplicable }
|
||||
}
|
||||
|
||||
let collectMissing = (rule) => {
|
||||
let collectMissing = rule => {
|
||||
let {
|
||||
formule,
|
||||
isApplicable,
|
||||
|
@ -498,8 +503,7 @@ export let treatRuleRoot = (rules, rule) => {
|
|||
return inversionMissingVariables
|
||||
}
|
||||
|
||||
let
|
||||
condMissing =
|
||||
let condMissing =
|
||||
val(notApplicable) === true
|
||||
? []
|
||||
: val(applicable) === false
|
||||
|
@ -599,12 +603,20 @@ let evolveCond = (name, rule, rules) => value => {
|
|||
}
|
||||
}
|
||||
|
||||
export let analyseSituation = (rules, rootVariable) => situationGate => {
|
||||
let { root } = analyseTopDown(rules, rootVariable)(situationGate)
|
||||
return root
|
||||
export let getTargets = (target, rules) => {
|
||||
let multiSimulation = R.path(['simulateur', 'objectifs'])(target)
|
||||
let targets = multiSimulation
|
||||
? // On a un simulateur qui définit une liste d'objectifs
|
||||
multiSimulation
|
||||
.map(n => disambiguateRuleReference(rules, target, n))
|
||||
.map(n => findRuleByDottedName(rules, n))
|
||||
: // Sinon on est dans le cas d'une simple variable d'objectif
|
||||
[target]
|
||||
|
||||
return targets
|
||||
}
|
||||
|
||||
export let analyseTopDown = (rules, rootVariable) => situationGate => {
|
||||
export let analyse = (rules, targetName) => situationGate => {
|
||||
clearDict()
|
||||
let /*
|
||||
La fonction treatRuleRoot va descendre l'arbre de la règle `rule` et produire un AST, un objet contenant d'autres objets contenant d'autres objets...
|
||||
|
@ -618,15 +630,17 @@ export let analyseTopDown = (rules, rootVariable) => situationGate => {
|
|||
parsedRules = R.map(treatOne, rules),
|
||||
// TODO: we should really make use of namespaces at this level, in particular
|
||||
// setRule in Rule.js needs to get smarter and pass dottedName
|
||||
rootRule = findRuleByName(parsedRules, rootVariable),
|
||||
parsedTarget = findRuleByName(parsedRules, targetName),
|
||||
/*
|
||||
Ce n'est que dans cette nouvelle étape que l'arbre est vraiment évalué.
|
||||
Auparavant, l'évaluation était faite lors de la construction de l'AST.
|
||||
*/
|
||||
root = evaluateNode(situationGate, parsedRules, rootRule)
|
||||
targets = getTargets(parsedTarget, parsedRules).map(t =>
|
||||
evaluateNode(situationGate, parsedRules, t)
|
||||
)
|
||||
|
||||
return {
|
||||
root,
|
||||
targets,
|
||||
parsedRules
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {nextSteps, makeQuestion} from 'Engine/generateQuestions'
|
|||
import computeThemeColours from 'Components/themeColours'
|
||||
import { STEP_ACTION, START_CONVERSATION, EXPLAIN_VARIABLE, CHANGE_THEME_COLOUR} from './actions'
|
||||
|
||||
import {analyseTopDown} from 'Engine/traverse'
|
||||
import {analyse} from 'Engine/traverse'
|
||||
|
||||
import ReactPiwik from 'Components/Tracker';
|
||||
|
||||
|
@ -39,9 +39,9 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (state, action) =
|
|||
if (![START_CONVERSATION, STEP_ACTION].includes(action.type))
|
||||
return state
|
||||
|
||||
let rootVariable = action.type == START_CONVERSATION ? action.rootVariable : state.analysedSituation.root.name
|
||||
let targetName = action.type == START_CONVERSATION ? action.targetName : state.targetName
|
||||
|
||||
let sim = findRuleByName(flatRules, rootVariable),
|
||||
let sim = findRuleByName(flatRules, targetName),
|
||||
// Hard assumptions cannot be changed, they are used to specialise a simulator
|
||||
// before the user sees the first question
|
||||
hardAssumptions = R.pathOr({},['simulateur','hypothèses'],sim),
|
||||
|
@ -51,18 +51,19 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (state, action) =
|
|||
completeSituation = assume(intermediateSituation,softAssumptions)
|
||||
|
||||
let situationGate = completeSituation(state),
|
||||
analysedSituation = analyseTopDown(flatRules,rootVariable)(situationGate)
|
||||
analysis = analyse(flatRules, targetName)(situationGate)
|
||||
|
||||
let newState = {
|
||||
...state,
|
||||
analysedSituation,
|
||||
targetName,
|
||||
analysis,
|
||||
situationGate: situationGate,
|
||||
extraSteps: [],
|
||||
explainedVariable: null
|
||||
}
|
||||
|
||||
if (action.type == START_CONVERSATION) {
|
||||
let next = nextSteps(situationGate, flatRules, newState.analysedSituation)
|
||||
let next = nextSteps(situationGate, flatRules, newState.analysis)
|
||||
|
||||
return {
|
||||
...newState,
|
||||
|
@ -74,7 +75,7 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (state, action) =
|
|||
tracker.push(['trackEvent', 'answer', action.step+": "+situationGate(action.step)]);
|
||||
|
||||
let foldedSteps = [...state.foldedSteps, state.currentQuestion],
|
||||
next = nextSteps(situationGate, flatRules, newState.analysedSituation),
|
||||
next = nextSteps(situationGate, flatRules, newState.analysis),
|
||||
assumptionsMade = !R.isEmpty(softAssumptions),
|
||||
done = next.length == 0
|
||||
|
||||
|
@ -82,10 +83,10 @@ export let reduceSteps = (tracker, flatRules, answerSource) => (state, action) =
|
|||
// where the answers were previously given default reasonable assumptions
|
||||
if (done && assumptionsMade) {
|
||||
let newSituation = intermediateSituation(state),
|
||||
reanalyse = analyseTopDown(flatRules,rootVariable)(newSituation),
|
||||
extraSteps = nextSteps(newSituation, flatRules, reanalyse)
|
||||
reanalysis = analyse(flatRules, targetName)(newSituation),
|
||||
extraSteps = nextSteps(newSituation, flatRules, reanalysis)
|
||||
|
||||
tracker.push(['trackEvent', 'done', 'extra questions: '+extraSteps.length]);
|
||||
tracker.push(['trackEvent', 'done', 'extra questions: '+extraSteps.length])
|
||||
|
||||
return {
|
||||
...newState,
|
||||
|
@ -154,7 +155,9 @@ export default reduceReducers(
|
|||
extraSteps: (steps = []) => steps,
|
||||
currentQuestion: (state = null) => state,
|
||||
|
||||
analysedSituation: (state = []) => state,
|
||||
analysis: (state = null) => state,
|
||||
|
||||
targetName: (state = null) => state,
|
||||
|
||||
situationGate: (state = name => null) => state,
|
||||
refine: (state = false) => state,
|
||||
|
|
|
@ -1,27 +1,12 @@
|
|||
import R from 'ramda'
|
||||
import {expect} from 'chai'
|
||||
import {rules as realRules, enrichRule} from '../source/engine/rules'
|
||||
import {analyseTopDown} from '../source/engine/traverse'
|
||||
import {nextSteps, collectMissingVariables, getObjectives} from '../source/engine/generateQuestions'
|
||||
import {analyse} from '../source/engine/traverse'
|
||||
import {nextSteps, collectMissingVariables} from '../source/engine/generateQuestions'
|
||||
|
||||
|
||||
let stateSelector = (name) => null
|
||||
|
||||
describe('getObjectives', function() {
|
||||
|
||||
it('should derive objectives from the root rule', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: 2, "non applicable si" : "sum . evt . ko", espace: "sum"},
|
||||
{nom: "evt", espace: "sum", formule: {"une possibilité":["ko"]}, titre: "Truc", question:"?"},
|
||||
{nom: "ko", espace: "sum . evt"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
{root, parsedRules} = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = getObjectives(stateSelector, root, parsedRules)
|
||||
|
||||
expect(result).to.have.lengthOf(1)
|
||||
expect(result[0]).to.have.property('name','startHere')
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('collectMissingVariables', function() {
|
||||
|
||||
|
@ -31,8 +16,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "evt", espace: "sum", formule: {"une possibilité":["ko"]}, titre: "Truc", question:"?"},
|
||||
{nom: "ko", espace: "sum . evt"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
expect(result).to.have.property('sum . evt . ko')
|
||||
});
|
||||
|
||||
|
@ -42,8 +27,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "nope", espace: "sum . evt"},
|
||||
{nom: "nyet", espace: "sum . evt"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.have.property('sum . evt . nyet')
|
||||
expect(result).to.have.property('sum . evt . nope')
|
||||
|
@ -54,8 +39,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "startHere", formule: "trois", "non applicable si" : "3 > 2", espace: "sum"},
|
||||
{nom: "trois", espace: "sum"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -65,8 +50,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "startHere", formule: "trois", "non applicable si" : {"une de ces conditions": ["3 > 2", "trois"]}, espace: "sum"},
|
||||
{nom: "trois", espace: "sum"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -76,8 +61,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "startHere", formule: "trois", espace: "top"},
|
||||
{nom: "trois", formule: {"une possibilité":["ko"]}, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.have.property('top . trois')
|
||||
});
|
||||
|
@ -87,8 +72,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "startHere", formule: "trois", espace: "top"},
|
||||
{nom: "trois", formule: {"une possibilité":["ko"]}, "non applicable si": 1, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -100,8 +85,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "startHere", formule: "trois", espace: "top"},
|
||||
{nom: "trois", formule: {"une possibilité":["ko"]}, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(mySelector),
|
||||
result = collectMissingVariables()(mySelector,situation)
|
||||
analysis = analyse(rules,"startHere")(mySelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -115,8 +100,8 @@ describe('collectMissingVariables', function() {
|
|||
}}, espace: "top"},
|
||||
{nom: "dix", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.have.property('top . dix')
|
||||
});
|
||||
|
@ -135,8 +120,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "dix", espace: "top"},
|
||||
{nom: "deux", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.have.property('top . dix')
|
||||
// expect(result).to.have.property('top . deux') - this is a TODO
|
||||
|
@ -156,8 +141,8 @@ describe('collectMissingVariables', function() {
|
|||
{nom: "dix", espace: "top"},
|
||||
{nom: "deux", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -170,8 +155,8 @@ describe('collectMissingVariables', function() {
|
|||
}}, espace: "top"},
|
||||
{nom: "dix", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -193,8 +178,8 @@ describe('collectMissingVariables', function() {
|
|||
{ nom: "dix", espace: "top" }
|
||||
],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules, "startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector, situation);
|
||||
analysis = analyse(rules, "startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
|
||||
expect(result).to.have.property('top . dix')
|
||||
|
@ -210,8 +195,8 @@ describe('collectMissingVariables', function() {
|
|||
}}, espace: "top"},
|
||||
{nom: "dix", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables()(stateSelector,situation)
|
||||
analysis = analyse(rules,"startHere")(stateSelector),
|
||||
result = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(result).to.deep.equal({})
|
||||
});
|
||||
|
@ -227,8 +212,8 @@ describe('nextSteps', function() {
|
|||
{nom: "evt", espace: "top . sum", formule: {"une possibilité":["ko"]}, titre: "Truc", question:"?"},
|
||||
{nom: "ko", espace: "top . sum . evt"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"sum")(stateSelector),
|
||||
result = nextSteps(stateSelector, rules, situation)
|
||||
analysis = analyse(rules,"sum")(stateSelector),
|
||||
result = nextSteps(stateSelector, rules, analysis)
|
||||
|
||||
expect(result).to.have.lengthOf(1)
|
||||
expect(result[0]).to.equal("top . sum . evt")
|
||||
|
@ -236,10 +221,9 @@ describe('nextSteps', function() {
|
|||
|
||||
it('should generate questions from the real rules', function() {
|
||||
let rules = realRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"surcoût CDD")(stateSelector),
|
||||
objectives = getObjectives(stateSelector, situation.root, situation.parsedRules),
|
||||
missing = collectMissingVariables()(stateSelector,situation),
|
||||
result = nextSteps(stateSelector, rules, situation)
|
||||
analysis = analyse(rules,"surcoût CDD")(stateSelector),
|
||||
missing = collectMissingVariables(analysis.targets),
|
||||
result = nextSteps(stateSelector, rules, analysis)
|
||||
|
||||
// expect(objectives).to.have.lengthOf(4)
|
||||
|
||||
|
@ -268,10 +252,9 @@ describe('nextSteps', function() {
|
|||
let stateSelector = (name) => ({"contrat salarié . type de contrat":"CDI","entreprise . effectif":"50"})[name]
|
||||
|
||||
let rules = realRules.map(enrichRule),
|
||||
situation = analyseTopDown(rules,"Salaire")(stateSelector),
|
||||
objectives = getObjectives(stateSelector, situation.root, situation.parsedRules),
|
||||
missing = collectMissingVariables()(stateSelector,situation),
|
||||
result = nextSteps(stateSelector, rules, situation)
|
||||
analysis = analyse(rules,"Salaire")(stateSelector),
|
||||
missing = collectMissingVariables(analysis.targets),
|
||||
result = nextSteps(stateSelector, rules, analysis)
|
||||
|
||||
expect(result[0]).to.equal("contrat salarié . salaire de base")
|
||||
expect(result[1]).to.equal("contrat salarié . temps partiel")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { expect } from "chai"
|
||||
import { enrichRule } from "../source/engine/rules"
|
||||
import { analyseTopDown, analyseSituation } from "../source/engine/traverse"
|
||||
import { analyse } from "../source/engine/traverse"
|
||||
import { collectMissingVariables } from "../source/engine/generateQuestions"
|
||||
import yaml from "js-yaml"
|
||||
import dedent from "dedent-js"
|
||||
|
@ -23,9 +23,9 @@ describe("inversions", () => {
|
|||
format: euro
|
||||
`,
|
||||
rules = yaml.safeLoad(rawRules).map(enrichRule),
|
||||
analysis = analyseSituation(rules, "net")(stateSelector)
|
||||
analysis = analyse(rules, "net")(stateSelector)
|
||||
|
||||
expect(analysis.nodeValue).to.be.closeTo(1771, 0.001)
|
||||
expect(analysis.targets[0].nodeValue).to.be.closeTo(1771, 0.001)
|
||||
})
|
||||
*/
|
||||
|
||||
|
@ -46,9 +46,9 @@ describe("inversions", () => {
|
|||
- net
|
||||
`,
|
||||
rules = yaml.safeLoad(rawRules).map(enrichRule),
|
||||
analysis = analyseSituation(rules, "brut")(stateSelector)
|
||||
analysis = analyse(rules, "brut")(stateSelector)
|
||||
|
||||
expect(analysis.nodeValue).to.be.closeTo(2000 / (77 / 100), 0.0001 * 2000)
|
||||
expect(analysis.targets[0].nodeValue).to.be.closeTo(2000 / (77 / 100), 0.0001 * 2000)
|
||||
})
|
||||
|
||||
it("should handle inversions with missing variables", () => {
|
||||
|
@ -71,10 +71,10 @@ describe("inversions", () => {
|
|||
`,
|
||||
rules = yaml.safeLoad(rawRules).map(enrichRule),
|
||||
stateSelector = name => ({ net: 2000 }[name]),
|
||||
analysis = analyseTopDown(rules, "brut")(stateSelector),
|
||||
missing = collectMissingVariables()(stateSelector, analysis)
|
||||
analysis = analyse(rules, "brut")(stateSelector),
|
||||
missing = collectMissingVariables(analysis.targets)
|
||||
|
||||
expect(analysis.root.nodeValue).to.be.null
|
||||
expect(analysis.targets[0].nodeValue).to.be.null
|
||||
expect(missing).to.have.key("cadre")
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import {expect} from 'chai'
|
||||
import {enrichRule} from '../source/engine/rules'
|
||||
import {analyseTopDown} from '../source/engine/traverse'
|
||||
import {analyse} from '../source/engine/traverse'
|
||||
import {collectMissingVariables} from '../source/engine/generateQuestions'
|
||||
import testSuites from './load-mecanism-tests'
|
||||
import R from 'ramda'
|
||||
|
@ -24,15 +24,16 @@ describe('Mécanismes', () =>
|
|||
let rules = suite.map(enrichRule),
|
||||
state = situation || {},
|
||||
stateSelector = name => state[name],
|
||||
analysis = analyseTopDown(rules, nom)(stateSelector),
|
||||
missing = collectMissingVariables()(stateSelector,analysis)
|
||||
analysis = analyse(rules, nom)(stateSelector),
|
||||
missing = collectMissingVariables(analysis.targets),
|
||||
target = analysis.targets[0]
|
||||
|
||||
// console.log('JSON.stringify(analysis', JSON.stringify(analysis))
|
||||
if (isFloat(valeur)) {
|
||||
expect(analysis.root.nodeValue).to.be.closeTo(valeur,0.001)
|
||||
expect(target.nodeValue).to.be.closeTo(valeur,0.001)
|
||||
}
|
||||
else if (valeur !== undefined) {
|
||||
expect(analysis.root)
|
||||
expect(target)
|
||||
.to.have.property(
|
||||
'nodeValue',
|
||||
valeur
|
||||
|
|
|
@ -2,7 +2,6 @@ import R from 'ramda'
|
|||
|
||||
import {expect} from 'chai'
|
||||
import {rules as realRules, enrichRule} from '../source/engine/rules'
|
||||
import {analyseSituation, analyseTopDown} from '../source/engine/traverse'
|
||||
import {collectMissingVariables, getObjectives} from '../source/engine/generateQuestions'
|
||||
|
||||
import {reduceSteps} from '../source/reducers'
|
||||
|
@ -22,10 +21,10 @@ describe('fold', function() {
|
|||
{nom: "bb", question: "?", titre: "b", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule),
|
||||
reducer = reduceSteps(tracker, rules, stateSelector),
|
||||
action = {type:'START_CONVERSATION', rootVariable: 'startHere'},
|
||||
action = {type:'START_CONVERSATION', targetName: 'startHere'},
|
||||
// situation = analyseTopDown(rules,"startHere")(stateSelector({})),
|
||||
// objectives = getObjectives(stateSelector({}), situation.root, situation.parsedRules),
|
||||
// missing = collectMissingVariables()(stateSelector({}),situation),
|
||||
// missing = collectMissingVariables(stateSelector({}),situation),
|
||||
result = reducer({},action)
|
||||
|
||||
expect(result).to.have.property('currentQuestion')
|
||||
|
@ -48,7 +47,7 @@ describe('fold', function() {
|
|||
rules = rawRules.map(enrichRule),
|
||||
reducer = reduceSteps(tracker, rules, stateSelector)
|
||||
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', rootVariable: 'startHere'})
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', targetName: 'startHere'})
|
||||
fakeState['top . aa'] = 1
|
||||
var step2 = reducer(step1,{type:'STEP_ACTION', name: 'fold', step: 'top . aa'})
|
||||
fakeState['top . bb'] = 1
|
||||
|
@ -82,7 +81,7 @@ describe('fold', function() {
|
|||
rules = rawRules.map(enrichRule),
|
||||
reducer = reduceSteps(tracker, rules, stateSelector)
|
||||
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', rootVariable: 'startHere'})
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', targetName: 'startHere'})
|
||||
fakeState['top . aa'] = 1
|
||||
var step2 = reducer(step1,{type:'STEP_ACTION', name: 'fold', step: 'top . aa'})
|
||||
|
||||
|
@ -116,7 +115,7 @@ describe('fold', function() {
|
|||
rules = rawRules.map(enrichRule),
|
||||
reducer = reduceSteps(tracker, rules, stateSelector)
|
||||
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', rootVariable: 'startHere'})
|
||||
var step1 = reducer({},{type:'START_CONVERSATION', targetName: 'startHere'})
|
||||
fakeState['top . aa'] = 1
|
||||
var step2 = reducer(step1,{type:'STEP_ACTION', name: 'fold', step: 'top . aa'})
|
||||
var step3 = reducer(step2,{type:'STEP_ACTION', name: 'unfold', step: 'top . bb'})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import R from 'ramda'
|
||||
import {expect} from 'chai'
|
||||
import {rules, enrichRule, findVariantsAndRecords} from '../source/engine/rules'
|
||||
import {analyseSituation, analyseTopDown} from '../source/engine/traverse'
|
||||
|
||||
let stateSelector = (state, name) => null
|
||||
|
||||
|
|
|
@ -1,33 +1,34 @@
|
|||
import {expect} from 'chai'
|
||||
import {rules as realRules, enrichRule} from '../source/engine/rules'
|
||||
import {analyseSituation, analyseTopDown} from '../source/engine/traverse'
|
||||
import {analyse, getTargets} from '../source/engine/traverse'
|
||||
|
||||
let stateSelector = (state, name) => null
|
||||
|
||||
describe('analyseSituation', function() {
|
||||
|
||||
describe('analyse', function() {
|
||||
|
||||
it('should directly return simple numerical values', function() {
|
||||
let rule = {name: "startHere", formule: 3269}
|
||||
let rules = [rule]
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3269)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3269)
|
||||
});
|
||||
|
||||
it('should compute expressions combining constants', function() {
|
||||
let rule = {name: "startHere", formule: "32 + 69"}
|
||||
let rules = [rule]
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',101)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',101)
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('analyseSituation on raw rules', function() {
|
||||
describe('analyse on raw rules', function() {
|
||||
|
||||
it('should handle direct referencing of a variable', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: "dix", espace: "top"},
|
||||
{nom: "dix", formule: 10, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',10)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',10)
|
||||
});
|
||||
|
||||
it('should handle expressions referencing other rules', function() {
|
||||
|
@ -35,7 +36,7 @@ describe('analyseSituation on raw rules', function() {
|
|||
{nom: "startHere", formule: "3259 + dix", espace: "top"},
|
||||
{nom: "dix", formule: 10, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3269)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3269)
|
||||
});
|
||||
|
||||
it('should handle applicability conditions', function() {
|
||||
|
@ -44,7 +45,7 @@ describe('analyseSituation on raw rules', function() {
|
|||
{nom: "dix", formule: 10, espace: "top", "non applicable si" : "vrai"},
|
||||
{nom: "vrai", formule: "2 > 1", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3259)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3259)
|
||||
});
|
||||
|
||||
it('should handle comparisons', function() {
|
||||
|
@ -52,7 +53,7 @@ describe('analyseSituation on raw rules', function() {
|
|||
{nom: "startHere", formule: "3259 > dix", espace: "top"},
|
||||
{nom: "dix", formule: 10, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',true)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',true)
|
||||
});
|
||||
|
||||
/* TODO: make this pass
|
||||
|
@ -62,26 +63,26 @@ describe('analyseSituation on raw rules', function() {
|
|||
{nom: "dix", formule: 10, espace: "top", "non applicable si" : "vrai"},
|
||||
{nom: "vrai", formule: "1", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3259)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3259)
|
||||
});
|
||||
*/
|
||||
|
||||
});
|
||||
|
||||
describe('analyseSituation with mecanisms', function() {
|
||||
describe('analyse with mecanisms', function() {
|
||||
|
||||
it('should handle n-way "or"', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: {"une de ces conditions": ["1 > 2", "1 > 0", "0 > 2"]}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',true)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',true)
|
||||
});
|
||||
|
||||
it('should handle n-way "and"', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: {"toutes ces conditions": ["1 > 2", "1 > 0", "0 > 2"]}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',false)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',false)
|
||||
});
|
||||
|
||||
it('should handle switch statements', function() {
|
||||
|
@ -93,14 +94,14 @@ describe('analyseSituation with mecanisms', function() {
|
|||
}}, espace: "top"},
|
||||
{nom: "dix", formule: 10, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',11)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',11)
|
||||
});
|
||||
|
||||
it('should handle percentages', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: "35%", espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',0.35)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',0.35)
|
||||
});
|
||||
|
||||
it('should handle sums', function() {
|
||||
|
@ -108,14 +109,14 @@ describe('analyseSituation with mecanisms', function() {
|
|||
{nom: "startHere", formule: {"somme": [3200, "dix", 9]}},
|
||||
{nom: "dix", formule: 10}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3219)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3219)
|
||||
});
|
||||
|
||||
it('should handle multiplications', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: {"multiplication": {assiette:3259, plafond:3200, facteur:1, taux:1.5}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',4800)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',4800)
|
||||
});
|
||||
|
||||
it('should handle components in multiplication', function() {
|
||||
|
@ -124,7 +125,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
composantes: [{taux:0.7}, {taux:0.8}]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',4800)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',4800)
|
||||
});
|
||||
|
||||
it('should apply a ceiling to the sum of components', function() {
|
||||
|
@ -133,7 +134,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
composantes: [{taux:0.7}, {taux:0.8}]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',4800)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',4800)
|
||||
});
|
||||
|
||||
it('should handle progressive scales', function() {
|
||||
|
@ -144,7 +145,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
"tranches":[{"en-dessous de":1, taux: 0.1},{de:1, "à": 2, taux: 1.2}, ,{"au-dessus de":2, taux: 10}]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',100+1200+80)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',100+1200+80)
|
||||
});
|
||||
|
||||
it('should handle progressive scales with components', function() {
|
||||
|
@ -158,7 +159,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',100+1200+80)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',100+1200+80)
|
||||
});
|
||||
|
||||
it('should handle progressive scales with variations', function() {
|
||||
|
@ -172,14 +173,14 @@ describe('analyseSituation with mecanisms', function() {
|
|||
]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',100+1800+80)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',100+1800+80)
|
||||
});
|
||||
|
||||
it('should handle max', function() {
|
||||
let rawRules = [
|
||||
{nom: "startHere", formule: {"le maximum de": [3200, 60, 9]}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',3200)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',3200)
|
||||
});
|
||||
|
||||
it('should handle complements', function() {
|
||||
|
@ -187,7 +188,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
{nom: "startHere", formule: {complément: {cible: "dix", montant: 93}}, espace: "top"},
|
||||
{nom: "dix", formule: 17, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',93-17)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',93-17)
|
||||
});
|
||||
|
||||
it('should handle components in complements', function() {
|
||||
|
@ -197,7 +198,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
}}, espace: "top"},
|
||||
{nom: "dix", formule: 17, espace: "top"}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',2*(93-17))
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',2*(93-17))
|
||||
});
|
||||
|
||||
it('should handle filtering on components', function() {
|
||||
|
@ -216,7 +217,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',50+400+40)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',50+400+40)
|
||||
});
|
||||
|
||||
it('should compute consistent values', function() {
|
||||
|
@ -236,8 +237,8 @@ describe('analyseSituation with mecanisms', function() {
|
|||
]
|
||||
}}}],
|
||||
rules = rawRules.map(enrichRule)
|
||||
expect(analyseSituation(rules,"orHere")(stateSelector)).to.have.property('nodeValue',100+1200+80)
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',100+1200+80)
|
||||
expect(analyse(rules,"orHere")(stateSelector).targets[0]).to.have.property('nodeValue',100+1200+80)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',100+1200+80)
|
||||
});
|
||||
|
||||
it('should handle selection', function() {
|
||||
|
@ -255,7 +256,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
données: 'taux_versement_transport'},
|
||||
{espace: "top", nom: "code postal", format: "nombre"}],
|
||||
rules = rawRules.map(rule => enrichRule(rule,data))
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue',0.02)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue',0.02)
|
||||
});
|
||||
|
||||
it('should handle failed selections', function() {
|
||||
|
@ -273,7 +274,7 @@ describe('analyseSituation with mecanisms', function() {
|
|||
données: 'taux_versement_transport'},
|
||||
{espace: "top", nom: "code postal", format: "nombre"}],
|
||||
rules = rawRules.map(rule => enrichRule(rule,data))
|
||||
expect(analyseSituation(rules,"startHere")(stateSelector)).to.have.property('nodeValue', 0)
|
||||
expect(analyse(rules,"startHere")(stateSelector).targets[0]).to.have.property('nodeValue', 0)
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue