Commit | Line | Data |
---|---|---|
43828378 BA |
1 | /* |
2 | * questions group by index prefix 1.2.3 1.1 ...etc --> '1' | |
3 | ||
4 | NOTE: questions can contain parameterized exercises (how ? | |
5 | --> describe variables (syntax ?) | |
6 | --> write javascript script (OK, users trusted ? ==> safe mode possible if public website) | |
7 | Imaginary example: (using math.js) | |
8 | <params> (avant l'exo) | |
9 | x: math.random() | |
10 | y: math.random() | |
11 | M: math.matrix([[7, x], [y, -3]]); | |
12 | res: math.det(M) | |
13 | </params> | |
14 | <div>Calculer le déterminant de | |
15 | $$\begin{matrix}7 & x\\y & -3\end{matrix}$$</div> | |
16 | * ... | |
17 | */ | |
18 | ||
435371c7 | 19 | Vue.component("statements", { |
8a51dbf7 BA |
20 | // 'answers' is an object containing |
21 | // 'inputs'(array), | |
e49ec3e4 | 22 | // 'displayAll'(bool), //TODO: should be in questions! |
8a51dbf7 BA |
23 | // 'showSolution'(bool), |
24 | // 'indices': order of appearance | |
25 | // 'index': current integer index (focused question) | |
26 | props: ['questions','answers'], | |
435371c7 BA |
27 | // TODO: general render function for nested exercises |
28 | // There should be a questions navigator below, or next (visible if display=='all') | |
29 | // Full questions tree is rendered, but some parts hidden depending on display settings | |
30 | render(h) { | |
8a51dbf7 | 31 | // TODO: render nothing if answers is empty |
71d1ca9c | 32 | let domTree = (this.questions || [ ]).map( (q,i) => { |
435371c7 BA |
33 | let questionContent = [ ]; |
34 | questionContent.push( | |
35 | h( | |
36 | "div", | |
37 | { | |
38 | "class": { | |
39 | wording: true, | |
40 | }, | |
41 | domProps: { | |
42 | innerHTML: q.wording, | |
43 | }, | |
44 | } | |
45 | ) | |
46 | ); | |
47 | let optionsOrder = _.range(q.options.length); | |
48 | if (!q.fixed) | |
49 | optionsOrder = _.shuffle(optionsOrder); | |
50 | let optionList = [ ]; | |
51 | optionsOrder.forEach( idx => { | |
52 | let option = [ ]; | |
53 | option.push( | |
54 | h( | |
55 | "input", | |
56 | { | |
57 | domProps: { | |
8a51dbf7 | 58 | checked: this.answers.inputs.length > 0 && this.answers.inputs[i][idx], |
435371c7 BA |
59 | disabled: monitoring, |
60 | }, | |
61 | attrs: { | |
62 | id: this.inputId(i,idx), | |
63 | type: "checkbox", | |
64 | }, | |
65 | on: { | |
8a51dbf7 | 66 | change: e => { this.answers.inputs[i][idx] = e.target.checked; }, |
435371c7 BA |
67 | }, |
68 | }, | |
8a2b3260 | 69 | [ '' ] //to work in Firefox 45.9 ESR @ ENSTA... |
435371c7 BA |
70 | ) |
71 | ); | |
72 | option.push( | |
73 | h( | |
74 | "label", | |
75 | { | |
76 | domProps: { | |
77 | innerHTML: q.options[idx], | |
78 | }, | |
79 | attrs: { | |
80 | "for": this.inputId(i,idx), | |
81 | }, | |
82 | } | |
83 | ) | |
84 | ); | |
85 | optionList.push( | |
86 | h( | |
87 | "div", | |
88 | { | |
89 | "class": { | |
90 | option: true, | |
8a51dbf7 | 91 | choiceCorrect: this.answers.showSolution && this.questions[i].answer.includes(idx), |
71d1ca9c | 92 | choiceWrong: this.answers.showSolution && this.answers.inputs[i][idx] && !q.answer.includes(idx), |
435371c7 BA |
93 | }, |
94 | }, | |
95 | option | |
96 | ) | |
97 | ); | |
98 | }); | |
99 | questionContent.push( | |
100 | h( | |
101 | "div", | |
102 | { | |
103 | "class": { | |
104 | optionList: true, | |
105 | }, | |
106 | }, | |
107 | optionList | |
108 | ) | |
109 | ); | |
e49ec3e4 BA |
110 | if (this.answers.displayAll && i < this.questions.length-1) |
111 | questionContent.push( h("hr") ); | |
435371c7 BA |
112 | return h( |
113 | "div", | |
114 | { | |
115 | "class": { | |
116 | "question": true, | |
71d1ca9c | 117 | "hide": !this.answers.displayAll && this.answers.indices[this.answers.index] != i, |
435371c7 BA |
118 | }, |
119 | }, | |
120 | questionContent | |
121 | ); | |
122 | }); | |
123 | return h( | |
124 | "div", | |
125 | { | |
126 | attrs: { | |
127 | id: "statements", | |
128 | }, | |
129 | }, | |
71d1ca9c | 130 | domTree |
435371c7 BA |
131 | ); |
132 | }, | |
3b8117c5 BA |
133 | mounted: function() { |
134 | statementsLibsRefresh(); | |
135 | }, | |
435371c7 BA |
136 | updated: function() { |
137 | // TODO: next line shouldn't be required: questions wordings + answer + options | |
138 | // are processed earlier; their content should be updated at this time. | |
139 | statementsLibsRefresh(); | |
140 | }, | |
141 | methods: { | |
142 | inputId: function(i,j) { | |
143 | return "q" + i + "_" + "input" + j; | |
144 | }, | |
145 | }, | |
146 | }); |