diff --git a/règles/rémunération-travail/entités/ok/CDD.yaml b/règles/rémunération-travail/entités/ok/CDD.yaml
index e315eec4a..671a6bc7d 100644
--- a/règles/rémunération-travail/entités/ok/CDD.yaml
+++ b/règles/rémunération-travail/entités/ok/CDD.yaml
@@ -78,3 +78,7 @@
titre: Votre obligation
motivation: Découvrez en quelques clics le montant des 4 obligations du CDD
# CIF, majoration chômage, indemnité de fin de contrat, indemnité compensatrice des congés payés
+ par défaut:
+ contrat salarié . CDD . événement: non
+ contrat salarié . CDD . congés non pris: 0
+ contrat salarié . CDD . contrat jeune vacances: non
diff --git a/source/components/Results.js b/source/components/Results.js
index bfcfecf84..edaa9e34a 100644
--- a/source/components/Results.js
+++ b/source/components/Results.js
@@ -22,7 +22,7 @@ let humanFigure = decimalDigits => value => fmt(value.toFixed(decimalDigits))
analysedSituation: state.analysedSituation,
conversationStarted: !R.isEmpty(state.form),
conversationFirstAnswer: R.path(['form', 'conversation', 'values'])(state),
- situationGate: (name => formValueSelector('conversation')(state, name))
+ situationGate: state.situationGate
})
)
export default class Results extends Component {
diff --git a/source/components/Simulateur.js b/source/components/Simulateur.js
index 5d432475e..1c2dc724f 100644
--- a/source/components/Simulateur.js
+++ b/source/components/Simulateur.js
@@ -24,6 +24,7 @@ let situationSelector = formValueSelector('conversation')
situation: variableName => situationSelector(state, variableName),
foldedSteps: state.foldedSteps,
unfoldedSteps: state.unfoldedSteps,
+ extraSteps: state.extraSteps,
themeColours: state.themeColours,
analysedSituation: state.analysedSituation,
}),
@@ -57,7 +58,7 @@ export default class extends React.Component {
let
started = !this.props.match.params.intro,
- {foldedSteps, unfoldedSteps, situation} = this.props,
+ {foldedSteps, extraSteps, unfoldedSteps, situation} = this.props,
sim = path =>
R.path(R.unless(R.is(Array), R.of)(path))(this.rule.simulateur || {}),
reinitalise = () => {
@@ -132,6 +133,22 @@ export default class extends React.Component {
))}
}
+ { !R.isEmpty(extraSteps) &&
+
+
+
Affiner votre situation
+
+ {extraSteps
+ .map(step => (
+
+ ))}
+
+ }
{ !R.isEmpty(unfoldedSteps) && do {
let step = R.head(unfoldedSteps)
diff --git a/source/reducers.js b/source/reducers.js
index 4189518ba..8ba4b1b88 100644
--- a/source/reducers.js
+++ b/source/reducers.js
@@ -4,58 +4,89 @@ import { combineReducers } from 'redux'
import reduceReducers from 'reduce-reducers'
import {reducer as formReducer, formValueSelector} from 'redux-form'
-import {rules} from 'Engine/rules'
-import {buildNextSteps, generateGridQuestions, generateSimpleQuestions} from 'Engine/generateQuestions'
+import {rules, findRuleByName } from 'Engine/rules'
+import {buildNextSteps} from 'Engine/generateQuestions'
import computeThemeColours from 'Components/themeColours'
import { STEP_ACTION, START_CONVERSATION, EXPLAIN_VARIABLE, POINT_OUT_OBJECTIVES, CHANGE_THEME_COLOUR} from './actions'
import {analyseTopDown} from 'Engine/traverse'
-let situationGate = state =>
- name => formValueSelector('conversation')(state, name)
+// Our situationGate retrieves data from the "conversation" form
+let fromConversation = state => name => formValueSelector('conversation')(state, name)
-let analyse = rootVariable => R.pipe(
- situationGate,
- // une liste des objectifs de la simulation (des 'rules' aussi nommées 'variables')
- analyseTopDown(rules, rootVariable)
-)
+// assume "wraps" a given situation function with one that overrides its values with
+// the given assumptions
+let assume = (evaluator, assumptions) => state => name =>
+ assumptions[name] != null ? assumptions[name] : evaluator(state)(name)
export let reduceSteps = (state, action) => {
+ let flatRules = rules
+
if (![START_CONVERSATION, STEP_ACTION].includes(action.type))
return state
let rootVariable = action.type == START_CONVERSATION ? action.rootVariable : state.analysedSituation.root.name
+ let sim = findRuleByName(flatRules, rootVariable),
+ // Hard assumptions cannot be changed, they are used to specialise a simulator
+ hardAssumptions = R.pathOr({},['simulateur','hypothèses'],sim),
+ // Soft assumptions are revealed after the simulation starts, and can be changed
+ softAssumptions = R.pathOr({},['simulateur','par défaut'],sim),
+ intermediateSituation = assume(fromConversation, hardAssumptions),
+ completeSituation = assume(intermediateSituation,softAssumptions)
+
+ let situationGate = completeSituation(state),
+ analysedSituation = analyseTopDown(flatRules,rootVariable)(situationGate)
+
let returnObject = {
...state,
- analysedSituation: analyse(rootVariable)(state)
+ analysedSituation,
+ situationGate: situationGate
}
if (action.type == START_CONVERSATION) {
return {
...returnObject,
foldedSteps: [],
- unfoldedSteps: buildNextSteps(situationGate(state), rules, returnObject.analysedSituation)
+ unfoldedSteps: buildNextSteps(situationGate, flatRules, returnObject.analysedSituation)
}
}
if (action.type == STEP_ACTION && action.name == 'fold') {
- return {
- ...returnObject,
- foldedSteps: [...state.foldedSteps, R.head(state.unfoldedSteps)],
- unfoldedSteps: buildNextSteps(situationGate(state), rules, returnObject.analysedSituation)
+ let foldedSteps = [...state.foldedSteps, R.head(state.unfoldedSteps)],
+ unfoldedSteps = buildNextSteps(situationGate, flatRules, returnObject.analysedSituation)
+
+ // The simulation is "over" - except we can now fill in extra questions
+ // where the answers were previously given reasonable assumptions
+ if (unfoldedSteps.length == 0 && !R.isEmpty(softAssumptions)) {
+ let newSituation = intermediateSituation(state),
+ reanalyse = analyseTopDown(flatRules,rootVariable)(newSituation),
+ extraSteps = buildNextSteps(newSituation, flatRules, reanalyse)
+
+ return {
+ ...returnObject,
+ foldedSteps,
+ extraSteps,
+ unfoldedSteps
+ }
}
- }
- if (action.type == STEP_ACTION && action.name == 'unfold') {
- let stepFinder = R.propEq('name', action.step),
- foldedSteps = R.reject(stepFinder)(state.foldedSteps)
- if (foldedSteps.length != state.foldedSteps.length - 1)
- throw 'Problème lors du dépliement d\'une réponse'
return {
...returnObject,
foldedSteps,
- unfoldedSteps: [R.find(stepFinder)(state.foldedSteps)]
+ unfoldedSteps
+ }
+ }
+ if (action.type == STEP_ACTION && action.name == 'unfold') {
+ let stepFinder = R.propEq('name', action.step),
+ foldedSteps = R.reject(stepFinder)(state.foldedSteps),
+ extraSteps = R.reject(stepFinder)(state.extraSteps)
+
+ return {
+ ...returnObject,
+ foldedSteps,
+ extraSteps,
+ unfoldedSteps: [R.find(stepFinder)(R.concat(state.foldedSteps,state.extraSteps))]
}
}
}
@@ -93,10 +124,14 @@ export default reduceReducers(
/* Have forms been filled or ignored ?
false means the user is reconsidering its previous input */
foldedSteps: (steps = []) => steps,
+ extraSteps: (steps = []) => steps,
unfoldedSteps: (steps = []) => steps,
analysedSituation: (state = []) => state,
+ situationGate: (state = state => name => null) => state,
+ refine: (state = false) => state,
+
themeColours,
explainedVariable,