From 61e11a648b7cfa3789ac0a6fec619ec836d3967f Mon Sep 17 00:00:00 2001 From: mama Date: Wed, 18 Oct 2017 10:45:20 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Corrige=20le=20pb=20de=20la=20double=20modi?= =?UTF-8?q?fication=20de=20r=C3=A9ponse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/reducers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/reducers.js b/source/reducers.js index abb6fd44f..d735f25ff 100644 --- a/source/reducers.js +++ b/source/reducers.js @@ -97,7 +97,7 @@ export let reduceSteps = (state, action) => { ReactPiwik.push(['trackEvent', 'unfold', action.step]); let stepFinder = R.propEq('name', action.step), - foldedSteps = R.reject(stepFinder)(state.foldedSteps), + foldedSteps = R.reject(stepFinder)(state.foldedSteps).concat(state.unfoldedSteps), extraSteps = R.reject(stepFinder)(state.extraSteps) return { From 6ba339cef1ceace0402fcb0ad4467a8573d88dc8 Mon Sep 17 00:00:00 2001 From: Laurent Bossavit Date: Sat, 14 Oct 2017 16:50:20 +0200 Subject: [PATCH 2/5] :white_check_mark: Introduit des tests pour reduceSteps --- source/reducers.js | 13 ++++++------- test/reducers.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 test/reducers.test.js diff --git a/source/reducers.js b/source/reducers.js index d735f25ff..e7afc6c91 100644 --- a/source/reducers.js +++ b/source/reducers.js @@ -23,10 +23,7 @@ let assume = (evaluator, assumptions) => state => name => { return userInput != null ? userInput : assumptions[name] } -export let reduceSteps = (state, action) => { - - let flatRules = rules - +export let reduceSteps = (flatRules, answerSource) => (state, action) => { if (![START_CONVERSATION, STEP_ACTION].includes(action.type)) return state @@ -38,7 +35,7 @@ export let reduceSteps = (state, action) => { hardAssumptions = R.pathOr({},['simulateur','hypothèses'],sim), // Soft assumptions are revealed after the simulation ends, and can be changed softAssumptions = R.pathOr({},['simulateur','par défaut'],sim), - intermediateSituation = assume(fromConversation, hardAssumptions), + intermediateSituation = assume(answerSource, hardAssumptions), completeSituation = assume(intermediateSituation,softAssumptions) let situationGate = completeSituation(state), @@ -52,10 +49,12 @@ export let reduceSteps = (state, action) => { } if (action.type == START_CONVERSATION) { + let unfoldedSteps = buildNextSteps(situationGate, flatRules, newState.analysedSituation) + return { ...newState, foldedSteps: [], - unfoldedSteps: buildNextSteps(situationGate, flatRules, newState.analysedSituation) + unfoldedSteps } } if (action.type == STEP_ACTION && action.name == 'fold') { @@ -148,5 +147,5 @@ export default reduceReducers( }), // cross-cutting concerns because here `state` is the whole state tree - reduceSteps + reduceSteps(rules, fromConversation) ) diff --git a/test/reducers.test.js b/test/reducers.test.js new file mode 100644 index 000000000..0a55c5560 --- /dev/null +++ b/test/reducers.test.js @@ -0,0 +1,34 @@ +import {expect} from 'chai' +import {rules as realRules, enrichRule} from '../source/engine/rules' +import {analyseSituation, analyseTopDown} from '../source/engine/traverse' +import {buildNextSteps, collectMissingVariables, getObjectives} from '../source/engine/generateQuestions' + +import {reduceSteps} from '../source/reducers' + +let stateSelector = state => name => null + +describe('fold', function() { + + it('should start conversation with only unfolded questions', function() { + let rawRules = [ + // TODO - this won't work without the indirection, figure out why + {nom: "startHere", formule: {somme: ["a","b"]}, espace: "top"}, + {nom: "a", espace: "top", formule: "aa"}, + {nom: "b", espace: "top", formule: "bb"}, + {nom: "aa", question: "?", titre: "a", espace: "top"}, + {nom: "bb", question: "?", titre: "b", espace: "top"}], + rules = rawRules.map(enrichRule), + reducer = reduceSteps(rules, stateSelector), + action = {type:'START_CONVERSATION', rootVariable: 'startHere'}, + // situation = analyseTopDown(rules,"startHere")(stateSelector({})), + // objectives = getObjectives(stateSelector({}), situation.root, situation.parsedRules), + // missing = collectMissingVariables()(stateSelector({}),situation), + result = reducer({},action) + + expect(result).to.have.property('unfoldedSteps') + expect(result.unfoldedSteps).to.have.lengthOf(2) + expect(result.unfoldedSteps[0]).to.have.deep.property("name","top . aa") + expect(result.unfoldedSteps[1]).to.have.deep.property("name","top . bb") + }); + +}); From 08d8ad08e148847f17b3fd0ce81d88f964f16a06 Mon Sep 17 00:00:00 2001 From: Laurent Bossavit Date: Sat, 14 Oct 2017 22:11:38 +0200 Subject: [PATCH 3/5] =?UTF-8?q?:gear:=20Injecter=20ReactPiwik=20comme=20d?= =?UTF-8?q?=C3=A9pendance=20de=20reduceSteps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/reducers.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/reducers.js b/source/reducers.js index e7afc6c91..6d09926c6 100644 --- a/source/reducers.js +++ b/source/reducers.js @@ -23,7 +23,7 @@ let assume = (evaluator, assumptions) => state => name => { return userInput != null ? userInput : assumptions[name] } -export let reduceSteps = (flatRules, answerSource) => (state, action) => { +export let reduceSteps = (tracker, flatRules, answerSource) => (state, action) => { if (![START_CONVERSATION, STEP_ACTION].includes(action.type)) return state @@ -58,7 +58,7 @@ export let reduceSteps = (flatRules, answerSource) => (state, action) => { } } if (action.type == STEP_ACTION && action.name == 'fold') { - ReactPiwik.push(['trackEvent', 'answer', action.step+": "+situationGate(action.step)]); + tracker.push(['trackEvent', 'answer', action.step+": "+situationGate(action.step)]); let foldedSteps = [...state.foldedSteps, R.head(state.unfoldedSteps)], unfoldedSteps = buildNextSteps(situationGate, flatRules, newState.analysedSituation), @@ -72,7 +72,7 @@ export let reduceSteps = (flatRules, answerSource) => (state, action) => { reanalyse = analyseTopDown(flatRules,rootVariable)(newSituation), extraSteps = buildNextSteps(newSituation, flatRules, reanalyse) - ReactPiwik.push(['trackEvent', 'done', 'extra questions: '+extraSteps.length]); + tracker.push(['trackEvent', 'done', 'extra questions: '+extraSteps.length]); return { ...newState, @@ -83,7 +83,7 @@ export let reduceSteps = (flatRules, answerSource) => (state, action) => { } if (done) { - ReactPiwik.push(['trackEvent', 'done', 'no more questions']); + tracker.push(['trackEvent', 'done', 'no more questions']); } return { @@ -93,7 +93,7 @@ export let reduceSteps = (flatRules, answerSource) => (state, action) => { } } if (action.type == STEP_ACTION && action.name == 'unfold') { - ReactPiwik.push(['trackEvent', 'unfold', action.step]); + tracker.push(['trackEvent', 'unfold', action.step]); let stepFinder = R.propEq('name', action.step), foldedSteps = R.reject(stepFinder)(state.foldedSteps).concat(state.unfoldedSteps), @@ -147,5 +147,5 @@ export default reduceReducers( }), // cross-cutting concerns because here `state` is the whole state tree - reduceSteps(rules, fromConversation) + reduceSteps(ReactPiwik, rules, fromConversation) ) From 2166968c412d6f4dbbbcedefd1510d13b2667308 Mon Sep 17 00:00:00 2001 From: Laurent Bossavit Date: Sat, 14 Oct 2017 22:11:56 +0200 Subject: [PATCH 4/5] =?UTF-8?q?:x:=20Mettre=20en=20=C3=A9vidence=20le=20bu?= =?UTF-8?q?g=20du=20double=20unfold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/reducers.test.js | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/test/reducers.test.js b/test/reducers.test.js index 0a55c5560..85d012ae9 100644 --- a/test/reducers.test.js +++ b/test/reducers.test.js @@ -1,3 +1,5 @@ +import R from 'ramda' + import {expect} from 'chai' import {rules as realRules, enrichRule} from '../source/engine/rules' import {analyseSituation, analyseTopDown} from '../source/engine/traverse' @@ -6,19 +8,20 @@ import {buildNextSteps, collectMissingVariables, getObjectives} from '../source/ import {reduceSteps} from '../source/reducers' let stateSelector = state => name => null +let tracker = {push: array => null} describe('fold', function() { it('should start conversation with only unfolded questions', function() { let rawRules = [ - // TODO - this won't work without the indirection, figure out why + // TODO - this won't work without the indirection, figure out why {nom: "startHere", formule: {somme: ["a","b"]}, espace: "top"}, {nom: "a", espace: "top", formule: "aa"}, {nom: "b", espace: "top", formule: "bb"}, {nom: "aa", question: "?", titre: "a", espace: "top"}, {nom: "bb", question: "?", titre: "b", espace: "top"}], rules = rawRules.map(enrichRule), - reducer = reduceSteps(rules, stateSelector), + reducer = reduceSteps(tracker, rules, stateSelector), action = {type:'START_CONVERSATION', rootVariable: 'startHere'}, // situation = analyseTopDown(rules,"startHere")(stateSelector({})), // objectives = getObjectives(stateSelector({}), situation.root, situation.parsedRules), @@ -31,4 +34,36 @@ describe('fold', function() { expect(result.unfoldedSteps[1]).to.have.deep.property("name","top . bb") }); + it('should deal with double unfold', function() { + let fakeState = {} + let stateSelector = state => name => fakeState[name] + + let rawRules = [ + // TODO - this won't work without the indirection, figure out why + {nom: "startHere", formule: {somme: ["a","b"]}, espace: "top"}, + {nom: "a", espace: "top", formule: "aa"}, + {nom: "b", espace: "top", formule: "bb"}, + {nom: "aa", question: "?", titre: "a", espace: "top"}, + {nom: "bb", question: "?", titre: "b", espace: "top"}], + rules = rawRules.map(enrichRule), + reducer = reduceSteps(tracker, rules, stateSelector) + + var step1 = reducer({},{type:'START_CONVERSATION', rootVariable: 'startHere'}) + fakeState['top . aa'] = 1 + var step2 = reducer(step1,{type:'STEP_ACTION', name: 'fold', step: 'top . aa'}) + fakeState['top . bb'] = 1 + var step3 = reducer(step2,{type:'STEP_ACTION', name: 'fold', step: 'top . bb'}) + var step4 = reducer(step3,{type:'STEP_ACTION', name: 'unfold', step: 'top . aa'}) + var step5 = reducer(step4,{type:'STEP_ACTION', name: 'unfold', step: 'top . bb'}) + + let result = step5 + + expect(result).to.have.property('unfoldedSteps') + expect(result.unfoldedSteps).to.have.lengthOf(1) + expect(result.unfoldedSteps[0]).to.have.deep.property("name","top . bb") + expect(result).to.have.property('foldedSteps') + expect(result.unfoldedSteps).to.have.lengthOf(1) + expect(result.unfoldedSteps[0]).to.have.deep.property("name","top . aa") + }); + }); From ffe7a8a308c7c3559f2c061be1c531c6ad89ca81 Mon Sep 17 00:00:00 2001 From: mama Date: Wed, 18 Oct 2017 16:05:38 +0200 Subject: [PATCH 5/5] Correction du test 'double unfold' --- test/reducers.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/reducers.test.js b/test/reducers.test.js index 85d012ae9..747d1042b 100644 --- a/test/reducers.test.js +++ b/test/reducers.test.js @@ -62,8 +62,8 @@ describe('fold', function() { expect(result.unfoldedSteps).to.have.lengthOf(1) expect(result.unfoldedSteps[0]).to.have.deep.property("name","top . bb") expect(result).to.have.property('foldedSteps') - expect(result.unfoldedSteps).to.have.lengthOf(1) - expect(result.unfoldedSteps[0]).to.have.deep.property("name","top . aa") + expect(result.foldedSteps).to.have.lengthOf(1) + expect(result.foldedSteps[0]).to.have.deep.property("name","top . aa") }); });