X-Git-Url: https://git.auder.net/images/pieces/Cwda/bg.svg?a=blobdiff_plain;f=public%2Fjavascripts%2Fcomponents%2Fstatements.js;h=6e12eb6109dac2a54571580b79ae2211ea041eb7;hb=cb39647ade2e424bcdf015228a7c1a09a92b5212;hp=900a5e7c698720220266d44bd36f436ccf67fdc2;hpb=a80c6a3b87f75653725f54caca1f24abc556afc7;p=qomet.git
diff --git a/public/javascripts/components/statements.js b/public/javascripts/components/statements.js
index 900a5e7..6e12eb6 100644
--- a/public/javascripts/components/statements.js
+++ b/public/javascripts/components/statements.js
@@ -14,127 +14,165 @@ Imaginary example: (using math.js)
Calculer le déterminant de
$$\begin{matrix}7 & x\\y & -3\end{matrix}$$
* ...
+
++ fixed + question time (syntax ?)
+
+--> input of type text (number, or vector, or matrix e.g. in R syntax)
+--> parameter stored in question.param (TODO)
+
*/
Vue.component("statements", {
- // 'inputs': array of index (as in questions) + input (text or array of ints)
+ // 'inputs': object with key = question index and value = text or boolean array
// display: 'all', 'one', 'solution'
// iidx: current level-0 integer index (can match a group of questions / inputs)
- props: ['questions','inputs','display','iidx'],
+ props: ['questions','inputs','answers','display','iidx'],
data: function() {
return {
displayStyle: "compact", //or "all": all on same page
+ parameters: 0, //TODO: DO NOT re-draw parameters for already answered questions
};
- }
+ },
// Full questions tree is rendered, but some parts hidden depending on display settings
render(h) {
- let domTree = (this.questions || [ ]).map( (q,i) => {
- let questionContent = [ ];
- questionContent.push(
- h(
- "h4",
- {
- "class": {
- "questionIndex": true,
- }
- },
- q.index
- )
- );
- questionContent.push(
- h(
- "div",
- {
- "class": {
- wording: true,
-
- },
- domProps: {
- innerHTML: q.wording,
+ // Prepare questions groups, ordered
+ let questions = this.questions || [ ]
+ let questionGroups = _.groupBy(questions, q => {
+ const dotPos = q.index.indexOf(".");
+ return dotPos === -1 ? q.index : q.index.substring(0,dotPos);
+ });
+ let domTree = questionGroups.map( (qg,i) => {
+ // Re-order questions 1.1.1 then 1.1.2 then...
+ const orderedQg = qg.sort( (a,b) => {
+ let aParts = a.split('.').map(Number);
+ let bParts = b.split('.').map(Number);
+ const La = aParts.length, Lb = bParts.length;
+ for (let i=0; i {
+ let questionContent = [ ];
+ questionContent.push(
+ h(
+ "h4",
+ {
+ "class": {
+ "questionIndex": true,
+ }
},
- }
- )
- );
- if (!!q.options)
- {
- // quiz-like question
- let optionsOrder = _.range(q.options.length);
- if (!q.fixed)
- optionsOrder = _.shuffle(optionsOrder);
- let optionList = [ ];
- optionsOrder.forEach( idx => {
- let option = [ ];
- option.push(
- h(
- "input",
- {
- domProps: {
- checked: this.answers.inputs.length > 0 && this.answers.inputs[i][idx],
- disabled: monitoring,
- },
- attrs: {
- id: this.inputId(i,idx),
- type: "checkbox",
- },
- on: {
- change: e => { this.answers.inputs[i][idx] = e.target.checked; },
- },
+ q.index
+ )
+ );
+ questionContent.push(
+ h(
+ "div",
+ {
+ "class": {
+ wording: true,
},
- [ '' ] //to work in Firefox 45.9 ESR @ ENSTA...
- )
- );
- option.push(
- h(
- "label",
- {
- domProps: {
- innerHTML: q.options[idx],
+ domProps: {
+ innerHTML: q.wording,
+ },
+ }
+ )
+ );
+ if (!!q.options)
+ {
+ // quiz-like question
+ let optionsOrder = _.range(q.options.length);
+ if (!q.fixed)
+ optionsOrder = _.shuffle(optionsOrder);
+ let optionList = [ ];
+ optionsOrder.forEach( idx => {
+ let option = [ ];
+ option.push(
+ h(
+ "input",
+ {
+ domProps: {
+ checked: !!this.inputs && this.inputs[q.index][idx],
+ disabled: monitoring || this.display == "solution",
+ },
+ attrs: {
+ id: this.inputId(q.index,idx),
+ type: "checkbox",
+ },
+ on: {
+ change: e => { this.inputs[q.index][idx] = e.target.checked; },
+ },
},
- attrs: {
- "for": this.inputId(i,idx),
+ [ '' ] //to work in Firefox 45.9 ESR @ ENSTA...
+ )
+ );
+ option.push(
+ h(
+ "label",
+ {
+ domProps: {
+ innerHTML: q.options[idx],
+ },
+ attrs: {
+ "for": this.inputId(q.index,idx),
+ },
+ }
+ )
+ );
+ const aIdx = (this.answers || [ ]).findIndex( item => { return item.index == q.index; });
+ optionList.push(
+ h(
+ "div",
+ {
+ "class": {
+ option: true,
+ choiceCorrect: this.display == "solution" && this.answers[aIdx].includes(idx),
+ choiceWrong: this.display == "solution" && !!this.inputs && this.inputs[q.index][idx] && !this.answers[aIdx].includes(idx),
+ },
},
- }
- )
- );
- optionList.push(
+ option
+ )
+ );
+ });
+ questionContent.push(
h(
"div",
{
"class": {
- option: true,
- choiceCorrect: this.answers.showSolution && this.questions[i].answer.includes(idx),
- choiceWrong: this.answers.showSolution && this.answers.inputs[i][idx] && !q.answer.includes(idx),
+ optionList: true,
},
},
- option
+ optionList
)
);
- });
- questionContent.push(
- h(
- "div",
- {
- "class": {
- optionList: true,
- },
+ }
+ else
+ {
+ // Open question, or parameterized: TODO
+ }
+ const depth = (q.index.match(/\./g) || []).length;
+ return h(
+ "div",
+ {
+ "class": {
+ "question": true,
+ ["depth" + depth]: true,
},
- optionList
- )
+ },
+ questionContent
);
- }
- if (this.display == "all" && !this.navigator && i < this.questions.length-1)
- questionContent.push( h("hr") );
- const depth = (q.index.match(/\./g) || []).length;
+ });
return h(
"div",
{
"class": {
- "question": true,
+ "questionGroup": true,
"hide": this.display == "one" && this.iidx != i,
- "depth" + depth: true,
},
},
- questionContent
+ qgDom
);
});
const navigator = h(
@@ -158,7 +196,7 @@ Vue.component("statements", {
},
},
[ h("span", { "class": { "material-icon": true } }, "fast_rewind") ]
- ), //onclick: index = max(0,index-1)
+ ),
h("span",{ },(this.iidx+1).toString()),
h(
"button",