2017-01-10 18:22:44 +00:00
import React from 'react'
2016-11-15 18:46:17 +00:00
import { combineReducers } from 'redux'
2017-01-10 18:22:44 +00:00
import reduceReducers from 'reduce-reducers'
import { reducer as formReducer , formValueSelector } from 'redux-form'
2017-03-16 18:30:30 +00:00
import { analyseSituation } from './engine/traverse'
2017-02-16 10:45:40 +00:00
import { euro , months } from './components/conversation/formValueTypes.js'
2017-01-10 18:22:44 +00:00
2017-03-16 18:30:30 +00:00
import { STEP _ACTION , START _CONVERSATION , EXPLAIN _VARIABLE , POINT _OUT _OBJECTIVES } from './actions'
2017-01-10 18:22:44 +00:00
import R from 'ramda'
2017-01-23 18:06:46 +00:00
2017-04-24 18:03:38 +00:00
import { findGroup , findRuleByDottedName , parentName , collectMissingVariables , recrecrecrec } from './engine/rules'
import { generateGridQuestions , generateSimpleQuestions } from './engine/generateQuestions'
2017-01-10 18:22:44 +00:00
import computeThemeColours from './components/themeColours'
function themeColours ( state = computeThemeColours ( ) , { type , colour } ) {
if ( type == 'CHANGE_THEME_COLOUR' )
return computeThemeColours ( colour )
else return state
}
2017-01-26 12:19:04 +00:00
let situationGate = state =>
name => formValueSelector ( 'conversation' ) ( state , name )
2017-02-09 17:38:51 +00:00
function explainedVariable ( state = null , { type , variableName = null } ) {
switch ( type ) {
case EXPLAIN _VARIABLE :
2017-02-09 17:15:25 +00:00
return variableName
2017-02-09 17:38:51 +00:00
default :
return state
}
2017-02-08 16:50:22 +00:00
}
2017-03-15 15:26:00 +00:00
function pointedOutObjectives ( state = [ ] , { type , objectives } ) {
switch ( type ) {
case POINT _OUT _OBJECTIVES :
return objectives
default :
return state
}
}
2017-03-22 17:18:37 +00:00
let handleSteps = ( state , action ) => {
2017-03-27 13:02:50 +00:00
if ( ! [ START _CONVERSATION , STEP _ACTION ] . includes ( action . type ) )
return state
2017-04-10 13:55:18 +00:00
let rootVariable = action . type == START _CONVERSATION ? action . rootVariable : state . analysedSituation . name
2017-03-22 17:18:37 +00:00
let returnObject = {
... state ,
2017-04-10 13:55:18 +00:00
analysedSituation : analyse ( rootVariable ) ( state )
2017-03-22 17:18:37 +00:00
}
2017-03-27 13:02:50 +00:00
2017-03-22 17:18:37 +00:00
if ( action . type == START _CONVERSATION ) {
return {
... returnObject ,
unfoldedSteps : buildNextSteps ( returnObject . analysedSituation )
}
}
if ( action . type == STEP _ACTION && action . name == 'fold' ) {
return {
... returnObject ,
foldedSteps : [ ... state . foldedSteps , R . head ( state . unfoldedSteps ) ] ,
unfoldedSteps : buildNextSteps ( returnObject . analysedSituation )
}
}
if ( action . type == STEP _ACTION && action . name == 'unfold' ) {
let stepFinder = R . propEq ( 'name' , action . step ) ,
foldedSteps = R . pipe (
R . splitWhen ( stepFinder ) ,
R . head
) ( state . foldedSteps )
return {
... returnObject ,
foldedSteps ,
unfoldedSteps : [ R . find ( stepFinder ) ( state . foldedSteps ) ]
}
}
}
2017-04-10 13:55:18 +00:00
let analyse = rootVariable => R . pipe (
2017-03-22 17:18:37 +00:00
situationGate ,
// une liste des objectifs de la simulation (des 'rules' aussi nommées 'variables')
2017-04-10 13:55:18 +00:00
analyseSituation ( rootVariable )
2017-03-22 17:18:37 +00:00
)
let missingVariables
let buildNextSteps = R . pipe (
/ *
2017-04-20 17:55:01 +00:00
COLLECTE DES VARIABLES MANQUANTES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2017-03-22 17:18:37 +00:00
on collecte les variables manquantes : celles qui sont nécessaires pour
remplir les objectifs de la simulation ( calculer des cotisations ) mais qui n ' ont pas
encore été renseignées
TODO perf : peut - on le faire en même temps que l 'on traverse l' AST ?
Oui sûrement , cette liste se complète en remontant l ' arbre . En fait , on le fait déjà pour nodeValue ,
et quand nodeValue vaut null , c 'est qu' il y a des missingVariables ! Il suffit donc de remplacer les
null par un tableau , et d 'ailleurs utiliser des fonction d' aide pour mutualiser ces tests .
missingVariables : { variable : [ objectives ] }
* /
R . path ( [ 'formule' , 'explanation' , 'explanation' ] ) ,
analysedSituation => {
2017-04-11 15:44:53 +00:00
// console.log('analysedSituation', analysedSituation)
2017-03-22 17:18:37 +00:00
//TODO temporary fix
missingVariables = collectMissingVariables ( 'groupByMissingVariable' ) ( analysedSituation )
return missingVariables
} ,
R . keys ,
/ *
2017-04-24 18:03:38 +00:00
Parmi les variables manquantes , certaines sont citées dans une règle de type 'une possibilité' .
* * On appelle ça des groupes de type 'variante' . * *
Il est alors plus intéressant de demander leur valeur dans un grille de possibilité plutôt que de façon indépendante .
2017-03-22 17:18:37 +00:00
Par exemple , au lieu de :
2017-04-24 18:03:38 +00:00
q1 : "Pensez vous prolonger le CDD en CDI" ,
2017-03-22 17:18:37 +00:00
r1 : Oui | Non
q2 : "Pensez-vous qu'une rupture pour faute grave est susceptible d'arriver"
r2 : Oui | Non
on préfère :
q : "Pensez-vous être confronté à l'un de ces événements ?"
2017-04-24 18:03:38 +00:00
r : Prolongation du CDD en CDI | Rupture pour faute grave .
Ceci est possible car ce sont tous les deux des événements et qu ' ils sont incompatibles entre eux .
Pour l 'instant, cela n' est possible que si les variables ont comme parent ( ou grand - parent ) ,
au sens de leur espace de nom , une règle de type 'une possibilité' .
# TODO pouvoir faire des variantes sans cette contrainte d ' espace de nom
D 'autres variables pourront être regroupées aussi, car elles partagent un parent, mais sans fusionner leurs questions dans l' interface . Ce sont des * * groupes de type _record _ * *
2017-03-22 17:18:37 +00:00
* /
2017-04-24 18:03:38 +00:00
R . reduce (
recrecrecrec //TODO reorganize
, { variantGroups : { } , recordGroups : { } }
) ,
2017-03-22 17:18:37 +00:00
// on va maintenant construire la liste des composants React qui afficheront les questions à l'utilisateur pour que l'on obtienne les variables manquantes
2017-04-24 18:03:38 +00:00
R . evolve ( {
variantGroups : generateGridQuestions ,
recordGroups : generateSimpleQuestions ,
} ) ,
R . values ,
R . unnest ,
2017-03-22 17:18:37 +00:00
)
2017-01-10 18:22:44 +00:00
export default reduceReducers (
combineReducers ( {
// this is handled by redux-form, pas touche !
form : formReducer ,
/ * H a v e f o r m s b e e n f i l l e d o r i g n o r e d ?
false means the user is reconsidering its previous input * /
2017-04-24 18:03:38 +00:00
foldedSteps : ( steps = [ ] ) => steps ,
unfoldedSteps : ( steps = [ ] ) => steps ,
2017-01-10 18:22:44 +00:00
analysedSituation : ( state = [ ] ) => state ,
2017-02-08 16:50:22 +00:00
themeColours ,
2017-03-15 15:26:00 +00:00
explainedVariable ,
2017-04-24 18:03:38 +00:00
pointedOutObjectives ,
2017-01-10 18:22:44 +00:00
} ) ,
// cross-cutting concerns because here `state` is the whole state tree
2017-03-22 17:18:37 +00:00
handleSteps
2017-01-10 18:22:44 +00:00
)