@pie-element/image-cloze-association 3.5.0 → 3.5.1-beta.587
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +478 -0
- package/configure/CHANGELOG.md +390 -0
- package/configure/lib/defaults.js +16 -0
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/index.js +17 -3
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js +43 -13
- package/configure/lib/root.js.map +1 -1
- package/configure/package.json +4 -3
- package/configure/src/__tests__/index.test.js +12 -15
- package/configure/src/defaults.js +20 -4
- package/configure/src/index.js +23 -3
- package/configure/src/root.jsx +41 -25
- package/controller/CHANGELOG.md +63 -0
- package/controller/lib/index.js +9 -8
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js +4 -4
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +2 -2
- package/controller/src/__tests__/index.test.js +108 -62
- package/controller/src/index.js +40 -28
- package/controller/src/utils.js +10 -10
- package/docs/config-schema.json +160 -0
- package/docs/config-schema.json.md +127 -0
- package/docs/demo/config.js +2 -2
- package/docs/demo/generate.js +30 -25
- package/docs/demo/session.js +1 -1
- package/docs/pie-schema.json +378 -0
- package/docs/pie-schema.json.md +295 -0
- package/lib/constants.js.map +1 -1
- package/lib/evaluation-icon.js.map +1 -1
- package/lib/image-container.js +13 -6
- package/lib/image-container.js.map +1 -1
- package/lib/image-drop-target.js +7 -2
- package/lib/image-drop-target.js.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/interactive-section.js +1 -1
- package/lib/interactive-section.js.map +1 -1
- package/lib/possible-response.js +17 -5
- package/lib/possible-response.js.map +1 -1
- package/lib/possible-responses.js.map +1 -1
- package/lib/root.js +140 -19
- package/lib/root.js.map +1 -1
- package/lib/utils-correctness.js +33 -5
- package/lib/utils-correctness.js.map +1 -1
- package/package.json +8 -5
- package/src/__tests__/__snapshots__/{image-container-test.jsx.snap → image-container.test.jsx.snap} +20 -0
- package/src/__tests__/__snapshots__/possible-response.test.jsx.snap +5 -0
- package/src/__tests__/__snapshots__/root.test.jsx.snap +50 -0
- package/src/__tests__/{image-container-test.jsx → image-container.test.jsx} +12 -5
- package/src/__tests__/{possible-response-test.jsx → possible-response.test.jsx} +5 -3
- package/src/__tests__/{root-test.jsx → root.test.jsx} +4 -3
- package/src/__tests__/utils.test.js +207 -0
- package/src/constants.js +3 -3
- package/src/evaluation-icon.jsx +8 -17
- package/src/image-container.jsx +14 -19
- package/src/image-drop-target.jsx +45 -38
- package/src/index.js +10 -18
- package/src/interactive-section.jsx +15 -22
- package/src/possible-response.jsx +43 -23
- package/src/possible-responses.jsx +17 -25
- package/src/root.jsx +174 -100
- package/src/utils-correctness.js +44 -14
- package/src/__tests__/__snapshots__/possible-response-test.jsx.snap +0 -13
- package/src/__tests__/__snapshots__/root-test.jsx.snap +0 -38
- package/src/__tests__/utils-test.js +0 -211
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
model,
|
|
3
|
-
outcome,
|
|
4
|
-
getPartialScore,
|
|
5
|
-
isResponseCorrect,
|
|
6
|
-
createCorrectResponseSession,
|
|
7
|
-
} from '../index';
|
|
1
|
+
import { model, outcome, getPartialScore, isResponseCorrect, createCorrectResponseSession } from '../index';
|
|
8
2
|
|
|
9
3
|
jest.mock('../utils', () => ({
|
|
10
4
|
...jest.requireActual('../utils.js'),
|
|
@@ -45,8 +39,12 @@ describe('controller', () => {
|
|
|
45
39
|
valid_response: {
|
|
46
40
|
score: 1,
|
|
47
41
|
value: [
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
{
|
|
43
|
+
images: [rhomb, square],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
images: [rhomb, square, trapeze],
|
|
47
|
+
},
|
|
50
48
|
],
|
|
51
49
|
},
|
|
52
50
|
},
|
|
@@ -61,11 +59,7 @@ describe('controller', () => {
|
|
|
61
59
|
describe('outcome partialScoring test', () => {
|
|
62
60
|
const assertOutcome = (message, extra, sessionValue, env, expected) => {
|
|
63
61
|
it(message, async () => {
|
|
64
|
-
const result = await outcome(
|
|
65
|
-
{ ...question, ...extra },
|
|
66
|
-
sessionValue,
|
|
67
|
-
env
|
|
68
|
-
);
|
|
62
|
+
const result = await outcome({ ...question, ...extra }, sessionValue, env);
|
|
69
63
|
|
|
70
64
|
expect(result).toEqual(expect.objectContaining(expected));
|
|
71
65
|
});
|
|
@@ -84,7 +78,7 @@ describe('controller', () => {
|
|
|
84
78
|
],
|
|
85
79
|
},
|
|
86
80
|
{ mode: 'evaluate' },
|
|
87
|
-
{ score: 0.2 }
|
|
81
|
+
{ score: 0.2 },
|
|
88
82
|
);
|
|
89
83
|
|
|
90
84
|
assertOutcome(
|
|
@@ -100,7 +94,7 @@ describe('controller', () => {
|
|
|
100
94
|
],
|
|
101
95
|
},
|
|
102
96
|
{ mode: 'evaluate' },
|
|
103
|
-
{ score: 0 }
|
|
97
|
+
{ score: 0 },
|
|
104
98
|
);
|
|
105
99
|
|
|
106
100
|
assertOutcome(
|
|
@@ -116,7 +110,7 @@ describe('controller', () => {
|
|
|
116
110
|
],
|
|
117
111
|
},
|
|
118
112
|
{ mode: 'evaluate', partialScoring: true },
|
|
119
|
-
{ score: 0 }
|
|
113
|
+
{ score: 0 },
|
|
120
114
|
);
|
|
121
115
|
|
|
122
116
|
assertOutcome(
|
|
@@ -132,15 +126,13 @@ describe('controller', () => {
|
|
|
132
126
|
],
|
|
133
127
|
},
|
|
134
128
|
{ mode: 'evaluate', partialScoring: false },
|
|
135
|
-
{ score: 0 }
|
|
129
|
+
{ score: 0 },
|
|
136
130
|
);
|
|
137
131
|
});
|
|
138
132
|
|
|
139
133
|
describe('outcome', () => {
|
|
140
134
|
const returnOutcome = (session) => {
|
|
141
|
-
it(`returns score of 0 and empty: true if session is ${JSON.stringify(
|
|
142
|
-
session
|
|
143
|
-
)}`, async () => {
|
|
135
|
+
it(`returns score of 0 and empty: true if session is ${JSON.stringify(session)}`, async () => {
|
|
144
136
|
const result = await outcome(question, session);
|
|
145
137
|
expect(result).toEqual({ score: 0, empty: true });
|
|
146
138
|
});
|
|
@@ -170,6 +162,76 @@ describe('controller', () => {
|
|
|
170
162
|
expect(result.score).toEqual(1);
|
|
171
163
|
});
|
|
172
164
|
|
|
165
|
+
describe('returns score 0 for wrong validation format', () => {
|
|
166
|
+
it('returns 0 for old value format', async () => {
|
|
167
|
+
const result = await outcome(
|
|
168
|
+
{
|
|
169
|
+
...question,
|
|
170
|
+
validation: {
|
|
171
|
+
valid_response: {
|
|
172
|
+
score: 1,
|
|
173
|
+
value: [
|
|
174
|
+
[rhomb, square],
|
|
175
|
+
[trapeze, hexagon],
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
answers: [
|
|
182
|
+
{ value: rhomb, containerIndex: 0 },
|
|
183
|
+
{ value: square, containerIndex: 0 },
|
|
184
|
+
{ value: trapeze, containerIndex: 1 },
|
|
185
|
+
{ value: hexagon, containerIndex: 1 },
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
expect(result.score).toEqual(0);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('returns 0 for when images is null ', async () => {
|
|
193
|
+
const result = await outcome(
|
|
194
|
+
{
|
|
195
|
+
...question,
|
|
196
|
+
validation: {
|
|
197
|
+
valid_response: {
|
|
198
|
+
score: 1,
|
|
199
|
+
value: [{ images: null }],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
answers: [
|
|
205
|
+
{ value: rhomb, containerIndex: 0 },
|
|
206
|
+
{ value: hexagon, containerIndex: 1 },
|
|
207
|
+
],
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
expect(result.score).toEqual(0);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('returns 0 for when value is [{}]', async () => {
|
|
214
|
+
const result = await outcome(
|
|
215
|
+
{
|
|
216
|
+
...question,
|
|
217
|
+
validation: {
|
|
218
|
+
valid_response: {
|
|
219
|
+
score: 1,
|
|
220
|
+
value: [{}],
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
answers: [
|
|
226
|
+
{ value: rhomb, containerIndex: 0 },
|
|
227
|
+
{ value: hexagon, containerIndex: 1 },
|
|
228
|
+
],
|
|
229
|
+
},
|
|
230
|
+
);
|
|
231
|
+
expect(result.score).toEqual(0);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
173
235
|
describe('alternate correct answers', () => {
|
|
174
236
|
describe('handles one option', async () => {
|
|
175
237
|
it('returns score of 1', async () => {
|
|
@@ -181,7 +243,7 @@ describe('controller', () => {
|
|
|
181
243
|
alt_responses: [
|
|
182
244
|
{
|
|
183
245
|
score: 1,
|
|
184
|
-
value: [[rhomb], [square], [trapeze], [hexagon]],
|
|
246
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
185
247
|
},
|
|
186
248
|
],
|
|
187
249
|
},
|
|
@@ -193,7 +255,7 @@ describe('controller', () => {
|
|
|
193
255
|
{ value: trapeze, containerIndex: 2 },
|
|
194
256
|
{ value: hexagon, containerIndex: 3 },
|
|
195
257
|
],
|
|
196
|
-
}
|
|
258
|
+
},
|
|
197
259
|
);
|
|
198
260
|
expect(result.score).toEqual(1);
|
|
199
261
|
});
|
|
@@ -207,7 +269,7 @@ describe('controller', () => {
|
|
|
207
269
|
alt_responses: [
|
|
208
270
|
{
|
|
209
271
|
score: 1,
|
|
210
|
-
value: [[rhomb], [square], [trapeze], [hexagon]],
|
|
272
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
211
273
|
},
|
|
212
274
|
],
|
|
213
275
|
},
|
|
@@ -219,7 +281,7 @@ describe('controller', () => {
|
|
|
219
281
|
{ value: trapeze, containerIndex: 2 },
|
|
220
282
|
{ value: hexagon, containerIndex: 0 },
|
|
221
283
|
],
|
|
222
|
-
}
|
|
284
|
+
},
|
|
223
285
|
);
|
|
224
286
|
expect(result.score).toEqual(0);
|
|
225
287
|
});
|
|
@@ -235,11 +297,11 @@ describe('controller', () => {
|
|
|
235
297
|
alt_responses: [
|
|
236
298
|
{
|
|
237
299
|
score: 1,
|
|
238
|
-
value: [[square], [rhomb], [
|
|
300
|
+
value: [{ images: [square] }, { images: [rhomb] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
239
301
|
},
|
|
240
302
|
{
|
|
241
303
|
score: 1,
|
|
242
|
-
value: [[rhomb], [square], [trapeze], [hexagon]],
|
|
304
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
243
305
|
},
|
|
244
306
|
],
|
|
245
307
|
},
|
|
@@ -251,7 +313,7 @@ describe('controller', () => {
|
|
|
251
313
|
{ value: trapeze, containerIndex: 2 },
|
|
252
314
|
{ value: hexagon, containerIndex: 3 },
|
|
253
315
|
],
|
|
254
|
-
}
|
|
316
|
+
},
|
|
255
317
|
);
|
|
256
318
|
expect(result.score).toEqual(1);
|
|
257
319
|
});
|
|
@@ -265,11 +327,11 @@ describe('controller', () => {
|
|
|
265
327
|
alt_responses: [
|
|
266
328
|
{
|
|
267
329
|
score: 1,
|
|
268
|
-
value: [[square], [rhomb], [
|
|
330
|
+
value: [{ images: [square] }, { images: [rhomb] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
269
331
|
},
|
|
270
332
|
{
|
|
271
333
|
score: 1,
|
|
272
|
-
value: [[rhomb], [square], [trapeze], [hexagon]],
|
|
334
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
273
335
|
},
|
|
274
336
|
],
|
|
275
337
|
},
|
|
@@ -281,7 +343,7 @@ describe('controller', () => {
|
|
|
281
343
|
{ value: trapeze, containerIndex: 2 },
|
|
282
344
|
{ value: hexagon, containerIndex: 0 },
|
|
283
345
|
],
|
|
284
|
-
}
|
|
346
|
+
},
|
|
285
347
|
);
|
|
286
348
|
expect(result.score).toEqual(0);
|
|
287
349
|
});
|
|
@@ -322,19 +384,13 @@ describe('controller', () => {
|
|
|
322
384
|
expect(result.validation).toEqual({
|
|
323
385
|
validResponse: {
|
|
324
386
|
score: 1,
|
|
325
|
-
value: [
|
|
326
|
-
[rhomb, square],
|
|
327
|
-
[rhomb, square, trapeze],
|
|
328
|
-
],
|
|
387
|
+
value: [{ images: [rhomb, square] }, { images: [rhomb, square, trapeze] }],
|
|
329
388
|
},
|
|
330
389
|
});
|
|
331
390
|
});
|
|
332
391
|
|
|
333
392
|
it('returns responseContainers', () => {
|
|
334
|
-
expect(result.responseContainers).toEqual([
|
|
335
|
-
responseContainer1,
|
|
336
|
-
responseContainer2,
|
|
337
|
-
]);
|
|
393
|
+
expect(result.responseContainers).toEqual([responseContainer1, responseContainer2]);
|
|
338
394
|
});
|
|
339
395
|
|
|
340
396
|
it('returns duplicateResponses', () => {
|
|
@@ -375,18 +431,12 @@ describe('controller', () => {
|
|
|
375
431
|
});
|
|
376
432
|
|
|
377
433
|
const returnModel = (sess) => {
|
|
378
|
-
it(`returns responseCorrect: false if session is ${JSON.stringify(
|
|
379
|
-
sess
|
|
380
|
-
)}`, async () => {
|
|
381
|
-
const result = await model(
|
|
382
|
-
question,
|
|
383
|
-
sess,
|
|
384
|
-
(env = { mode: 'evaluate' })
|
|
385
|
-
);
|
|
434
|
+
it(`returns responseCorrect: false if session is ${JSON.stringify(sess)}`, async () => {
|
|
435
|
+
const result = await model(question, sess, (env = { mode: 'evaluate' }));
|
|
386
436
|
expect(result).toEqual(
|
|
387
437
|
expect.objectContaining({
|
|
388
438
|
responseCorrect: false,
|
|
389
|
-
})
|
|
439
|
+
}),
|
|
390
440
|
);
|
|
391
441
|
});
|
|
392
442
|
};
|
|
@@ -462,12 +512,12 @@ describe('createCorrectResponseSession', () => {
|
|
|
462
512
|
valid_response: {
|
|
463
513
|
score: 1,
|
|
464
514
|
value: [
|
|
465
|
-
|
|
466
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
470
|
-
|
|
515
|
+
{
|
|
516
|
+
images: ['<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>'],
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
images: ['<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>'],
|
|
520
|
+
},
|
|
471
521
|
],
|
|
472
522
|
},
|
|
473
523
|
},
|
|
@@ -482,13 +532,11 @@ describe('createCorrectResponseSession', () => {
|
|
|
482
532
|
expect(sess).toEqual({
|
|
483
533
|
answers: [
|
|
484
534
|
{
|
|
485
|
-
value:
|
|
486
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
535
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
487
536
|
containerIndex: 0,
|
|
488
537
|
},
|
|
489
538
|
{
|
|
490
|
-
value:
|
|
491
|
-
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
539
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
492
540
|
containerIndex: 1,
|
|
493
541
|
},
|
|
494
542
|
],
|
|
@@ -505,13 +553,11 @@ describe('createCorrectResponseSession', () => {
|
|
|
505
553
|
expect(sess).toEqual({
|
|
506
554
|
answers: [
|
|
507
555
|
{
|
|
508
|
-
value:
|
|
509
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
556
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
510
557
|
containerIndex: 0,
|
|
511
558
|
},
|
|
512
559
|
{
|
|
513
|
-
value:
|
|
514
|
-
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
560
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
515
561
|
containerIndex: 1,
|
|
516
562
|
},
|
|
517
563
|
],
|
package/controller/src/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { getAllUniqueCorrectness } from './utils';
|
|
|
7
7
|
|
|
8
8
|
const log = debug('pie-elements:image-cloze-association:controller');
|
|
9
9
|
|
|
10
|
-
export const normalize = question => ({
|
|
10
|
+
export const normalize = (question) => ({
|
|
11
11
|
rationaleEnabled: true,
|
|
12
12
|
teacherInstructionsEnabled: true,
|
|
13
13
|
studentInstructionsEnabled: true,
|
|
@@ -18,19 +18,18 @@ export function model(question, session, env) {
|
|
|
18
18
|
const questionNormalized = normalize(question);
|
|
19
19
|
const questionCamelized = camelizeKeys(questionNormalized);
|
|
20
20
|
|
|
21
|
-
return new Promise(resolve => {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
22
|
const out = {
|
|
23
23
|
disabled: env.mode !== 'gather',
|
|
24
24
|
mode: env.mode,
|
|
25
25
|
...questionCamelized,
|
|
26
|
-
responseCorrect:
|
|
27
|
-
env.mode === 'evaluate'
|
|
28
|
-
? getScore(questionCamelized, session) === 1
|
|
29
|
-
: undefined,
|
|
26
|
+
responseCorrect: env.mode === 'evaluate' ? getScore(questionCamelized, session) === 1 : undefined,
|
|
30
27
|
};
|
|
31
28
|
|
|
32
29
|
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
33
|
-
out.teacherInstructions = questionCamelized.teacherInstructionsEnabled
|
|
30
|
+
out.teacherInstructions = questionCamelized.teacherInstructionsEnabled
|
|
31
|
+
? questionCamelized.teacherInstructions
|
|
32
|
+
: null;
|
|
34
33
|
} else {
|
|
35
34
|
out.teacherInstructions = null;
|
|
36
35
|
}
|
|
@@ -47,11 +46,11 @@ export const isResponseCorrect = (responses, session) => {
|
|
|
47
46
|
return false;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
responses.forEach(value => totalValidResponses += value.length);
|
|
49
|
+
responses.forEach((value) => (totalValidResponses += (value.images || []).length));
|
|
51
50
|
|
|
52
51
|
if (session.answers && totalValidResponses === session.answers.length) {
|
|
53
|
-
session.answers.forEach(answer => {
|
|
54
|
-
if (!responses[answer.containerIndex].includes(answer.value)) {
|
|
52
|
+
session.answers.forEach((answer) => {
|
|
53
|
+
if (!(responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
55
54
|
isCorrect = false;
|
|
56
55
|
}
|
|
57
56
|
});
|
|
@@ -63,13 +62,18 @@ export const isResponseCorrect = (responses, session) => {
|
|
|
63
62
|
|
|
64
63
|
// This applies for items that don't support partial scoring.
|
|
65
64
|
const isDefaultOrAltResponseCorrect = (question, session) => {
|
|
66
|
-
const {
|
|
65
|
+
const {
|
|
66
|
+
validation: {
|
|
67
|
+
validResponse: { value },
|
|
68
|
+
altResponses,
|
|
69
|
+
},
|
|
70
|
+
} = question;
|
|
67
71
|
|
|
68
72
|
let isCorrect = isResponseCorrect(value, session);
|
|
69
73
|
|
|
70
74
|
// Look for correct answers in alternate responses.
|
|
71
|
-
if (!isCorrect &&
|
|
72
|
-
altResponses.forEach(altResponse => {
|
|
75
|
+
if (!isCorrect && altResponses && altResponses.length) {
|
|
76
|
+
altResponses.forEach((altResponse) => {
|
|
73
77
|
if (isResponseCorrect(altResponse.value, session)) {
|
|
74
78
|
isCorrect = true;
|
|
75
79
|
}
|
|
@@ -80,9 +84,9 @@ const isDefaultOrAltResponseCorrect = (question, session) => {
|
|
|
80
84
|
|
|
81
85
|
// Deduct only the items that exceeded the maximum valid response per container.
|
|
82
86
|
const getDeductionPerContainer = (containerIndex, answers, valid) => {
|
|
83
|
-
const totalStack = answers.filter(item => item.containerIndex === containerIndex);
|
|
84
|
-
const incorrectStack = totalStack.filter(item => !item.isCorrect);
|
|
85
|
-
const maxValid = valid.value[containerIndex].length;
|
|
87
|
+
const totalStack = answers.filter((item) => item.containerIndex === containerIndex);
|
|
88
|
+
const incorrectStack = totalStack.filter((item) => !item.isCorrect);
|
|
89
|
+
const maxValid = (valid.value[containerIndex].images || []).length;
|
|
86
90
|
|
|
87
91
|
if (totalStack.length > maxValid) {
|
|
88
92
|
const ignored = totalStack.length - maxValid;
|
|
@@ -92,7 +96,11 @@ const getDeductionPerContainer = (containerIndex, answers, valid) => {
|
|
|
92
96
|
};
|
|
93
97
|
|
|
94
98
|
export const getPartialScore = (question, session) => {
|
|
95
|
-
const {
|
|
99
|
+
const {
|
|
100
|
+
validation: { validResponse },
|
|
101
|
+
maxResponsePerZone,
|
|
102
|
+
responseContainers,
|
|
103
|
+
} = question;
|
|
96
104
|
let correctAnswers = 0;
|
|
97
105
|
let possibleResponses = 0;
|
|
98
106
|
|
|
@@ -100,19 +108,19 @@ export const getPartialScore = (question, session) => {
|
|
|
100
108
|
return 0;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
|
-
validResponse.value.forEach(value => possibleResponses += value.length);
|
|
111
|
+
validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));
|
|
104
112
|
|
|
105
113
|
if (session.answers && session.answers.length) {
|
|
106
114
|
const all = getAllUniqueCorrectness(session.answers, validResponse.value);
|
|
107
|
-
correctAnswers = all.filter(item => item.isCorrect).length;
|
|
115
|
+
correctAnswers = all.filter((item) => item.isCorrect).length;
|
|
108
116
|
|
|
109
117
|
// deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit
|
|
110
|
-
session.answers.forEach(answer => {
|
|
118
|
+
session.answers.forEach((answer) => {
|
|
111
119
|
if (maxResponsePerZone > 1) {
|
|
112
120
|
const deductionList = getDeductionPerContainer(answer.containerIndex, all, validResponse);
|
|
113
121
|
|
|
114
122
|
if (deductionList.length) {
|
|
115
|
-
deductionList.forEach(item => {
|
|
123
|
+
deductionList.forEach((item) => {
|
|
116
124
|
if (item.id === answer.id) {
|
|
117
125
|
correctAnswers -= 1;
|
|
118
126
|
}
|
|
@@ -136,11 +144,11 @@ const getScore = (config, session, env = {}) => {
|
|
|
136
144
|
const isPartialScoring = partialScoring.enabled(config, env);
|
|
137
145
|
const correct = isDefaultOrAltResponseCorrect(config, session);
|
|
138
146
|
|
|
139
|
-
return isPartialScoring ? getPartialScore(config, session) :
|
|
147
|
+
return isPartialScoring ? getPartialScore(config, session) : correct ? 1 : 0;
|
|
140
148
|
};
|
|
141
149
|
|
|
142
150
|
export function outcome(config, session, env = {}) {
|
|
143
|
-
return new Promise(resolve => {
|
|
151
|
+
return new Promise((resolve) => {
|
|
144
152
|
log('outcome...');
|
|
145
153
|
if (!session || isEmpty(session)) {
|
|
146
154
|
resolve({ score: 0, empty: true });
|
|
@@ -156,17 +164,21 @@ export function outcome(config, session, env = {}) {
|
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
export const createCorrectResponseSession = (question, env) => {
|
|
159
|
-
return new Promise(resolve => {
|
|
167
|
+
return new Promise((resolve) => {
|
|
160
168
|
if (env.mode !== 'evaluate' && env.role === 'instructor') {
|
|
161
|
-
const {
|
|
169
|
+
const {
|
|
170
|
+
validation: {
|
|
171
|
+
valid_response: { value },
|
|
172
|
+
},
|
|
173
|
+
} = question;
|
|
162
174
|
const answers = [];
|
|
163
175
|
|
|
164
176
|
if (value) {
|
|
165
177
|
value.forEach((container, i) => {
|
|
166
|
-
container.forEach(v => {
|
|
178
|
+
(container.images || []).forEach((v) => {
|
|
167
179
|
answers.push({
|
|
168
180
|
value: v,
|
|
169
|
-
containerIndex: i
|
|
181
|
+
containerIndex: i,
|
|
170
182
|
});
|
|
171
183
|
});
|
|
172
184
|
});
|
|
@@ -174,7 +186,7 @@ export const createCorrectResponseSession = (question, env) => {
|
|
|
174
186
|
|
|
175
187
|
resolve({
|
|
176
188
|
answers,
|
|
177
|
-
id: '1'
|
|
189
|
+
id: '1',
|
|
178
190
|
});
|
|
179
191
|
} else {
|
|
180
192
|
resolve(null);
|
package/controller/src/utils.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
const getAllCorrectness = (answers, responses) =>
|
|
2
|
-
answers.map(answer => ({
|
|
2
|
+
answers.map((answer) => ({
|
|
3
3
|
...answer,
|
|
4
|
-
isCorrect: responses[answer.containerIndex].includes(answer.value)
|
|
4
|
+
isCorrect: (responses[answer.containerIndex].images || []).includes(answer.value),
|
|
5
5
|
}));
|
|
6
6
|
|
|
7
7
|
const getValidAnswer = (answer, response) =>
|
|
8
|
-
response[answer.containerIndex].filter(res => res === answer.value);
|
|
8
|
+
(response[answer.containerIndex].images || []).filter((res) => res === answer.value);
|
|
9
9
|
|
|
10
10
|
export const getAllUniqueCorrectness = (answers, validResponses) => {
|
|
11
11
|
let allCorrectness = getAllCorrectness(answers, validResponses);
|
|
12
12
|
|
|
13
13
|
answers.forEach((answer1) => {
|
|
14
|
-
const valuesToParse = answers.filter(
|
|
15
|
-
(answer2.value === answer1.value
|
|
14
|
+
const valuesToParse = answers.filter(
|
|
15
|
+
(answer2) => answer2.value === answer1.value && answer2.containerIndex === answer1.containerIndex,
|
|
16
|
+
);
|
|
16
17
|
|
|
17
18
|
if (valuesToParse.length > 1) {
|
|
18
19
|
// point only to duplicates but first
|
|
19
20
|
valuesToParse.shift();
|
|
20
21
|
// mark duplicates as incorrect
|
|
21
22
|
valuesToParse.forEach((value, index) => {
|
|
22
|
-
allCorrectness = allCorrectness.map(finalAnswer => {
|
|
23
|
+
allCorrectness = allCorrectness.map((finalAnswer) => {
|
|
23
24
|
if (finalAnswer.id === value.id) {
|
|
24
25
|
let valid = getValidAnswer(finalAnswer, validResponses);
|
|
25
|
-
|
|
26
26
|
return {
|
|
27
27
|
...finalAnswer,
|
|
28
|
-
isCorrect: valid.length > index + 1
|
|
29
|
-
}
|
|
28
|
+
isCorrect: valid.length > index + 1,
|
|
29
|
+
};
|
|
30
30
|
}
|
|
31
31
|
return finalAnswer;
|
|
32
|
-
})
|
|
32
|
+
});
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
});
|