@pie-element/image-cloze-association 4.3.3-next.8 → 4.3.3-next.90
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/configure/lib/defaults.js.map +1 -1
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js.map +1 -1
- package/configure/package.json +2 -2
- package/configure/src/__tests__/index.test.js +12 -15
- package/configure/src/defaults.js +8 -8
- package/configure/src/index.js +4 -4
- package/configure/src/root.jsx +7 -20
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js.map +1 -1
- package/controller/src/__tests__/index.test.js +34 -67
- package/controller/src/index.js +38 -26
- package/controller/src/utils.js +10 -9
- package/docs/config-schema.json.md +1 -1
- package/docs/demo/config.js +2 -2
- package/docs/demo/generate.js +20 -17
- package/docs/demo/session.js +1 -1
- package/docs/pie-schema.json.md +1 -1
- package/lib/constants.js.map +1 -1
- package/lib/evaluation-icon.js.map +1 -1
- package/lib/image-container.js.map +1 -1
- package/lib/image-drop-target.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interactive-section.js.map +1 -1
- package/lib/possible-response.js.map +1 -1
- package/lib/possible-responses.js.map +1 -1
- package/lib/root.js.map +1 -1
- package/lib/utils-correctness.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/image-container.test.jsx +5 -5
- package/src/__tests__/possible-response.test.jsx +2 -2
- package/src/__tests__/root.test.jsx +3 -3
- package/src/__tests__/utils.test.js +144 -148
- package/src/constants.js +3 -3
- package/src/evaluation-icon.jsx +8 -17
- package/src/image-container.jsx +11 -19
- package/src/image-drop-target.jsx +40 -39
- package/src/index.js +5 -18
- package/src/interactive-section.jsx +15 -22
- package/src/possible-response.jsx +30 -23
- package/src/possible-responses.jsx +17 -25
- package/src/root.jsx +29 -69
- package/src/utils-correctness.js +31 -23
|
@@ -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'),
|
|
@@ -46,10 +40,10 @@ describe('controller', () => {
|
|
|
46
40
|
score: 1,
|
|
47
41
|
value: [
|
|
48
42
|
{
|
|
49
|
-
images: [rhomb, square]
|
|
43
|
+
images: [rhomb, square],
|
|
50
44
|
},
|
|
51
45
|
{
|
|
52
|
-
images: [rhomb, square, trapeze]
|
|
46
|
+
images: [rhomb, square, trapeze],
|
|
53
47
|
},
|
|
54
48
|
],
|
|
55
49
|
},
|
|
@@ -65,11 +59,7 @@ describe('controller', () => {
|
|
|
65
59
|
describe('outcome partialScoring test', () => {
|
|
66
60
|
const assertOutcome = (message, extra, sessionValue, env, expected) => {
|
|
67
61
|
it(message, async () => {
|
|
68
|
-
const result = await outcome(
|
|
69
|
-
{ ...question, ...extra },
|
|
70
|
-
sessionValue,
|
|
71
|
-
env
|
|
72
|
-
);
|
|
62
|
+
const result = await outcome({ ...question, ...extra }, sessionValue, env);
|
|
73
63
|
|
|
74
64
|
expect(result).toEqual(expect.objectContaining(expected));
|
|
75
65
|
});
|
|
@@ -88,7 +78,7 @@ describe('controller', () => {
|
|
|
88
78
|
],
|
|
89
79
|
},
|
|
90
80
|
{ mode: 'evaluate' },
|
|
91
|
-
{ score: 0.2 }
|
|
81
|
+
{ score: 0.2 },
|
|
92
82
|
);
|
|
93
83
|
|
|
94
84
|
assertOutcome(
|
|
@@ -104,7 +94,7 @@ describe('controller', () => {
|
|
|
104
94
|
],
|
|
105
95
|
},
|
|
106
96
|
{ mode: 'evaluate' },
|
|
107
|
-
{ score: 0 }
|
|
97
|
+
{ score: 0 },
|
|
108
98
|
);
|
|
109
99
|
|
|
110
100
|
assertOutcome(
|
|
@@ -120,7 +110,7 @@ describe('controller', () => {
|
|
|
120
110
|
],
|
|
121
111
|
},
|
|
122
112
|
{ mode: 'evaluate', partialScoring: true },
|
|
123
|
-
{ score: 0 }
|
|
113
|
+
{ score: 0 },
|
|
124
114
|
);
|
|
125
115
|
|
|
126
116
|
assertOutcome(
|
|
@@ -136,15 +126,13 @@ describe('controller', () => {
|
|
|
136
126
|
],
|
|
137
127
|
},
|
|
138
128
|
{ mode: 'evaluate', partialScoring: false },
|
|
139
|
-
{ score: 0 }
|
|
129
|
+
{ score: 0 },
|
|
140
130
|
);
|
|
141
131
|
});
|
|
142
132
|
|
|
143
133
|
describe('outcome', () => {
|
|
144
134
|
const returnOutcome = (session) => {
|
|
145
|
-
it(`returns score of 0 and empty: true if session is ${JSON.stringify(
|
|
146
|
-
session
|
|
147
|
-
)}`, async () => {
|
|
135
|
+
it(`returns score of 0 and empty: true if session is ${JSON.stringify(session)}`, async () => {
|
|
148
136
|
const result = await outcome(question, session);
|
|
149
137
|
expect(result).toEqual({ score: 0, empty: true });
|
|
150
138
|
});
|
|
@@ -184,7 +172,7 @@ describe('controller', () => {
|
|
|
184
172
|
score: 1,
|
|
185
173
|
value: [
|
|
186
174
|
[rhomb, square],
|
|
187
|
-
[trapeze, hexagon]
|
|
175
|
+
[trapeze, hexagon],
|
|
188
176
|
],
|
|
189
177
|
},
|
|
190
178
|
},
|
|
@@ -196,7 +184,7 @@ describe('controller', () => {
|
|
|
196
184
|
{ value: trapeze, containerIndex: 1 },
|
|
197
185
|
{ value: hexagon, containerIndex: 1 },
|
|
198
186
|
],
|
|
199
|
-
}
|
|
187
|
+
},
|
|
200
188
|
);
|
|
201
189
|
expect(result.score).toEqual(0);
|
|
202
190
|
});
|
|
@@ -208,9 +196,7 @@ describe('controller', () => {
|
|
|
208
196
|
validation: {
|
|
209
197
|
valid_response: {
|
|
210
198
|
score: 1,
|
|
211
|
-
value: [
|
|
212
|
-
{ images: null }
|
|
213
|
-
],
|
|
199
|
+
value: [{ images: null }],
|
|
214
200
|
},
|
|
215
201
|
},
|
|
216
202
|
},
|
|
@@ -219,7 +205,7 @@ describe('controller', () => {
|
|
|
219
205
|
{ value: rhomb, containerIndex: 0 },
|
|
220
206
|
{ value: hexagon, containerIndex: 1 },
|
|
221
207
|
],
|
|
222
|
-
}
|
|
208
|
+
},
|
|
223
209
|
);
|
|
224
210
|
expect(result.score).toEqual(0);
|
|
225
211
|
});
|
|
@@ -231,9 +217,7 @@ describe('controller', () => {
|
|
|
231
217
|
validation: {
|
|
232
218
|
valid_response: {
|
|
233
219
|
score: 1,
|
|
234
|
-
value: [
|
|
235
|
-
{}
|
|
236
|
-
],
|
|
220
|
+
value: [{}],
|
|
237
221
|
},
|
|
238
222
|
},
|
|
239
223
|
},
|
|
@@ -242,11 +226,10 @@ describe('controller', () => {
|
|
|
242
226
|
{ value: rhomb, containerIndex: 0 },
|
|
243
227
|
{ value: hexagon, containerIndex: 1 },
|
|
244
228
|
],
|
|
245
|
-
}
|
|
229
|
+
},
|
|
246
230
|
);
|
|
247
231
|
expect(result.score).toEqual(0);
|
|
248
232
|
});
|
|
249
|
-
|
|
250
233
|
});
|
|
251
234
|
|
|
252
235
|
describe('alternate correct answers', () => {
|
|
@@ -260,7 +243,7 @@ describe('controller', () => {
|
|
|
260
243
|
alt_responses: [
|
|
261
244
|
{
|
|
262
245
|
score: 1,
|
|
263
|
-
value: [{images: [rhomb]}, {images: [square]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
246
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
264
247
|
},
|
|
265
248
|
],
|
|
266
249
|
},
|
|
@@ -272,7 +255,7 @@ describe('controller', () => {
|
|
|
272
255
|
{ value: trapeze, containerIndex: 2 },
|
|
273
256
|
{ value: hexagon, containerIndex: 3 },
|
|
274
257
|
],
|
|
275
|
-
}
|
|
258
|
+
},
|
|
276
259
|
);
|
|
277
260
|
expect(result.score).toEqual(1);
|
|
278
261
|
});
|
|
@@ -286,7 +269,7 @@ describe('controller', () => {
|
|
|
286
269
|
alt_responses: [
|
|
287
270
|
{
|
|
288
271
|
score: 1,
|
|
289
|
-
value: [{images: [rhomb]}, {images: [square]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
272
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
290
273
|
},
|
|
291
274
|
],
|
|
292
275
|
},
|
|
@@ -298,7 +281,7 @@ describe('controller', () => {
|
|
|
298
281
|
{ value: trapeze, containerIndex: 2 },
|
|
299
282
|
{ value: hexagon, containerIndex: 0 },
|
|
300
283
|
],
|
|
301
|
-
}
|
|
284
|
+
},
|
|
302
285
|
);
|
|
303
286
|
expect(result.score).toEqual(0);
|
|
304
287
|
});
|
|
@@ -314,11 +297,11 @@ describe('controller', () => {
|
|
|
314
297
|
alt_responses: [
|
|
315
298
|
{
|
|
316
299
|
score: 1,
|
|
317
|
-
value: [{images: [square]}, {images: [rhomb]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
300
|
+
value: [{ images: [square] }, { images: [rhomb] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
318
301
|
},
|
|
319
302
|
{
|
|
320
303
|
score: 1,
|
|
321
|
-
value: [{images: [rhomb]}, {images: [square]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
304
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
322
305
|
},
|
|
323
306
|
],
|
|
324
307
|
},
|
|
@@ -330,7 +313,7 @@ describe('controller', () => {
|
|
|
330
313
|
{ value: trapeze, containerIndex: 2 },
|
|
331
314
|
{ value: hexagon, containerIndex: 3 },
|
|
332
315
|
],
|
|
333
|
-
}
|
|
316
|
+
},
|
|
334
317
|
);
|
|
335
318
|
expect(result.score).toEqual(1);
|
|
336
319
|
});
|
|
@@ -344,11 +327,11 @@ describe('controller', () => {
|
|
|
344
327
|
alt_responses: [
|
|
345
328
|
{
|
|
346
329
|
score: 1,
|
|
347
|
-
value: [{images: [square]}, {images: [rhomb]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
330
|
+
value: [{ images: [square] }, { images: [rhomb] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
348
331
|
},
|
|
349
332
|
{
|
|
350
333
|
score: 1,
|
|
351
|
-
value: [{images: [rhomb]}, {images: [square]}, {images: [trapeze]}, {images: [hexagon]}],
|
|
334
|
+
value: [{ images: [rhomb] }, { images: [square] }, { images: [trapeze] }, { images: [hexagon] }],
|
|
352
335
|
},
|
|
353
336
|
],
|
|
354
337
|
},
|
|
@@ -360,7 +343,7 @@ describe('controller', () => {
|
|
|
360
343
|
{ value: trapeze, containerIndex: 2 },
|
|
361
344
|
{ value: hexagon, containerIndex: 0 },
|
|
362
345
|
],
|
|
363
|
-
}
|
|
346
|
+
},
|
|
364
347
|
);
|
|
365
348
|
expect(result.score).toEqual(0);
|
|
366
349
|
});
|
|
@@ -401,19 +384,13 @@ describe('controller', () => {
|
|
|
401
384
|
expect(result.validation).toEqual({
|
|
402
385
|
validResponse: {
|
|
403
386
|
score: 1,
|
|
404
|
-
value: [
|
|
405
|
-
{images: [rhomb, square]},
|
|
406
|
-
{images: [rhomb, square, trapeze]},
|
|
407
|
-
],
|
|
387
|
+
value: [{ images: [rhomb, square] }, { images: [rhomb, square, trapeze] }],
|
|
408
388
|
},
|
|
409
389
|
});
|
|
410
390
|
});
|
|
411
391
|
|
|
412
392
|
it('returns responseContainers', () => {
|
|
413
|
-
expect(result.responseContainers).toEqual([
|
|
414
|
-
responseContainer1,
|
|
415
|
-
responseContainer2,
|
|
416
|
-
]);
|
|
393
|
+
expect(result.responseContainers).toEqual([responseContainer1, responseContainer2]);
|
|
417
394
|
});
|
|
418
395
|
|
|
419
396
|
it('returns duplicateResponses', () => {
|
|
@@ -454,18 +431,12 @@ describe('controller', () => {
|
|
|
454
431
|
});
|
|
455
432
|
|
|
456
433
|
const returnModel = (sess) => {
|
|
457
|
-
it(`returns responseCorrect: false if session is ${JSON.stringify(
|
|
458
|
-
sess
|
|
459
|
-
)}`, async () => {
|
|
460
|
-
const result = await model(
|
|
461
|
-
question,
|
|
462
|
-
sess,
|
|
463
|
-
(env = { mode: 'evaluate' })
|
|
464
|
-
);
|
|
434
|
+
it(`returns responseCorrect: false if session is ${JSON.stringify(sess)}`, async () => {
|
|
435
|
+
const result = await model(question, sess, (env = { mode: 'evaluate' }));
|
|
465
436
|
expect(result).toEqual(
|
|
466
437
|
expect.objectContaining({
|
|
467
438
|
responseCorrect: false,
|
|
468
|
-
})
|
|
439
|
+
}),
|
|
469
440
|
);
|
|
470
441
|
});
|
|
471
442
|
};
|
|
@@ -561,13 +532,11 @@ describe('createCorrectResponseSession', () => {
|
|
|
561
532
|
expect(sess).toEqual({
|
|
562
533
|
answers: [
|
|
563
534
|
{
|
|
564
|
-
value:
|
|
565
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
535
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
566
536
|
containerIndex: 0,
|
|
567
537
|
},
|
|
568
538
|
{
|
|
569
|
-
value:
|
|
570
|
-
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
539
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
571
540
|
containerIndex: 1,
|
|
572
541
|
},
|
|
573
542
|
],
|
|
@@ -584,13 +553,11 @@ describe('createCorrectResponseSession', () => {
|
|
|
584
553
|
expect(sess).toEqual({
|
|
585
554
|
answers: [
|
|
586
555
|
{
|
|
587
|
-
value:
|
|
588
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
556
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
589
557
|
containerIndex: 0,
|
|
590
558
|
},
|
|
591
559
|
{
|
|
592
|
-
value:
|
|
593
|
-
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
560
|
+
value: '<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
594
561
|
containerIndex: 1,
|
|
595
562
|
},
|
|
596
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,10 +46,10 @@ export const isResponseCorrect = (responses, session) => {
|
|
|
47
46
|
return false;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
responses.forEach(value => totalValidResponses += (value.images || []).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 => {
|
|
52
|
+
session.answers.forEach((answer) => {
|
|
54
53
|
if (!(responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
55
54
|
isCorrect = false;
|
|
56
55
|
}
|
|
@@ -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,8 +84,8 @@ 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);
|
|
87
|
+
const totalStack = answers.filter((item) => item.containerIndex === containerIndex);
|
|
88
|
+
const incorrectStack = totalStack.filter((item) => !item.isCorrect);
|
|
85
89
|
const maxValid = (valid.value[containerIndex].images || []).length;
|
|
86
90
|
|
|
87
91
|
if (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.images || []).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.images || []).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,34 +1,35 @@
|
|
|
1
1
|
const getAllCorrectness = (answers, responses) =>
|
|
2
|
-
answers.map(answer => ({
|
|
2
|
+
answers.map((answer) => ({
|
|
3
3
|
...answer,
|
|
4
|
-
isCorrect: (responses[answer.containerIndex].images || []).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].images || []).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
|
return {
|
|
26
27
|
...finalAnswer,
|
|
27
|
-
isCorrect: valid.length > index + 1
|
|
28
|
-
}
|
|
28
|
+
isCorrect: valid.length > index + 1,
|
|
29
|
+
};
|
|
29
30
|
}
|
|
30
31
|
return finalAnswer;
|
|
31
|
-
})
|
|
32
|
+
});
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
});
|
package/docs/demo/config.js
CHANGED
package/docs/demo/generate.js
CHANGED
|
@@ -6,14 +6,15 @@ exports.model = (id, element) => ({
|
|
|
6
6
|
src: 'https://app.fluence.net/ia/image/6412223997a34018b15f8512bee6c04c',
|
|
7
7
|
width: 465,
|
|
8
8
|
scale: false, // this is not used
|
|
9
|
-
height: 313
|
|
9
|
+
height: 313,
|
|
10
10
|
},
|
|
11
|
-
response_container: {
|
|
11
|
+
response_container: {
|
|
12
|
+
// this is not used
|
|
12
13
|
wordwrap: true,
|
|
13
14
|
width: '130px',
|
|
14
|
-
height: '55px'
|
|
15
|
+
height: '55px',
|
|
15
16
|
},
|
|
16
|
-
metadata: {}
|
|
17
|
+
metadata: {}, // this is not used
|
|
17
18
|
is_math: true, // this is not used
|
|
18
19
|
response_id: '8a808081592940240159464a277609e7', // this is not used
|
|
19
20
|
response_containers: [
|
|
@@ -24,7 +25,7 @@ exports.model = (id, element) => ({
|
|
|
24
25
|
width: '35.70%',
|
|
25
26
|
y: 1.6,
|
|
26
27
|
height: '23.64%',
|
|
27
|
-
aria_label: '' // this is not used
|
|
28
|
+
aria_label: '', // this is not used
|
|
28
29
|
},
|
|
29
30
|
{
|
|
30
31
|
pointer: 'undefined', // this is not used
|
|
@@ -33,19 +34,21 @@ exports.model = (id, element) => ({
|
|
|
33
34
|
width: '35.92%',
|
|
34
35
|
y: 39.62,
|
|
35
36
|
height: '23.32%',
|
|
36
|
-
aria_label: '' // this is not used
|
|
37
|
-
}
|
|
37
|
+
aria_label: '', // this is not used
|
|
38
|
+
},
|
|
38
39
|
],
|
|
39
40
|
stimulus:
|
|
40
41
|
'<p>A car manufacturer proposes the development of a car tire disposal area near an important wetland habitat. In this area, tires will be broken into pieces and buried. The manufacturer needs to design this area to address the environmental concerns from the list in the passage. After breaking the tires into pieces, the manufacturer decides to recycle some of the pieces and dispose of the rest in this newly developed area. Drag and drop the data labels into the graph to show how this decision will likely affect the number of tire pieces collected from a sample area of the wetland after many years.</p>',
|
|
41
|
-
|
|
42
|
+
// this is not used
|
|
43
|
+
metadatadistractor_rationale:
|
|
42
44
|
'<p>A correct response is shown below. This response best shows how this decision will likely affect the number tire pieces collected.<img alt="image 03de38019abe41b1bc95d1199658327f" id="03de38019abe41b1bc95d1199658327f" src="https://localhost:8443/ia/image/03de38019abe41b1bc95d1199658327f" /></p>',
|
|
43
|
-
ui_style: {
|
|
44
|
-
|
|
45
|
+
ui_style: {
|
|
46
|
+
// this is not used
|
|
47
|
+
fontsize: 'small',
|
|
45
48
|
},
|
|
46
49
|
possible_responses: [
|
|
47
50
|
'<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>',
|
|
48
|
-
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>'
|
|
51
|
+
'<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>',
|
|
49
52
|
],
|
|
50
53
|
validation: {
|
|
51
54
|
scoring_type: 'exactMatch', // this is not used
|
|
@@ -53,16 +56,16 @@ exports.model = (id, element) => ({
|
|
|
53
56
|
score: 1,
|
|
54
57
|
value: [
|
|
55
58
|
{
|
|
56
|
-
images: ['<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>']
|
|
59
|
+
images: ['<img alt="" src="https://app.fluence.net/ia/image/729ca157d04c440ab7ae1c2abfb9c057"/>'],
|
|
57
60
|
},
|
|
58
61
|
{
|
|
59
|
-
images: ['<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>']
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
|
62
|
+
images: ['<img alt="" src="https://app.fluence.net/ia/image/9e5ed1d6762c4dac87b080e190af113d"/>'],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
63
66
|
},
|
|
64
67
|
showDashedBorder: false,
|
|
65
68
|
partialScoring: false,
|
|
66
69
|
shuffle: true, // this is not used
|
|
67
|
-
rubricEnabled: false
|
|
70
|
+
rubricEnabled: false,
|
|
68
71
|
});
|
package/docs/demo/session.js
CHANGED
package/docs/pie-schema.json.md
CHANGED
package/lib/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.js"],"names":["types","response"],"mappings":";;;;;;eAAe;AACbA,EAAAA,KAAK,EAAE;AACLC,IAAAA,QAAQ,EAAE;AADL;AADM,C","sourcesContent":["export default {\n types: {\n response: 'react-dnd-response'
|
|
1
|
+
{"version":3,"sources":["../src/constants.js"],"names":["types","response"],"mappings":";;;;;;eAAe;AACbA,EAAAA,KAAK,EAAE;AACLC,IAAAA,QAAQ,EAAE;AADL;AADM,C","sourcesContent":["export default {\n types: {\n response: 'react-dnd-response',\n },\n};\n"],"file":"constants.js"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/evaluation-icon.jsx"],"names":["getCorrectnessClass","isCorrect","filled","EvaluationIcon","classes","containerStyle","Icon","Check","Close","showCorrectness","undefined","correctness","icon","propTypes","PropTypes","object","bool","oneOfType","number","defaultProps","styles","correctEmpty","color","correct","correctFilled","background","backgroundColor","incorrectEmpty","incorrect","incorrectFilled"],"mappings":";;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAEA,IAAMA,mBAAmB,GAAG,SAAtBA,mBAAsB,CAACC,SAAD,EAAYC,MAAZ,EAAuB;AACjD,MAAIA,MAAJ,EAAY;AACV,WAAOD,SAAS,GAAG,eAAH,GAAqB,iBAArC;AACD;;AACD,SAAOA,SAAS,GAAG,cAAH,GAAoB,gBAApC;AACD,CALD;;AAOA,IAAME,cAAc,GAAG,SAAjBA,cAAiB,OAAoD;AAAA,MAAjDC,OAAiD,QAAjDA,OAAiD;AAAA,MAAxCC,cAAwC,QAAxCA,cAAwC;AAAA,MAAxBJ,SAAwB,QAAxBA,SAAwB;AAAA,MAAbC,MAAa,QAAbA,MAAa;AACzE,MAAMI,IAAI,GAAGL,SAAS,GAAGM,iBAAH,GAAWC,iBAAjC;AACA,MAAMC,eAAe,GAAGR,SAAS,KAAKS,SAAtC;AACA,MAAMC,WAAW,GAAGF,eAAe,GAAGT,mBAAmB,CAACC,SAAD,EAAYC,MAAZ,CAAtB,GAA4C,EAA/E;AAEA,SAAOO,eAAe,
|
|
1
|
+
{"version":3,"sources":["../src/evaluation-icon.jsx"],"names":["getCorrectnessClass","isCorrect","filled","EvaluationIcon","classes","containerStyle","Icon","Check","Close","showCorrectness","undefined","correctness","icon","propTypes","PropTypes","object","bool","oneOfType","number","defaultProps","styles","correctEmpty","color","correct","correctFilled","background","backgroundColor","incorrectEmpty","incorrect","incorrectFilled"],"mappings":";;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAEA,IAAMA,mBAAmB,GAAG,SAAtBA,mBAAsB,CAACC,SAAD,EAAYC,MAAZ,EAAuB;AACjD,MAAIA,MAAJ,EAAY;AACV,WAAOD,SAAS,GAAG,eAAH,GAAqB,iBAArC;AACD;;AACD,SAAOA,SAAS,GAAG,cAAH,GAAoB,gBAApC;AACD,CALD;;AAOA,IAAME,cAAc,GAAG,SAAjBA,cAAiB,OAAoD;AAAA,MAAjDC,OAAiD,QAAjDA,OAAiD;AAAA,MAAxCC,cAAwC,QAAxCA,cAAwC;AAAA,MAAxBJ,SAAwB,QAAxBA,SAAwB;AAAA,MAAbC,MAAa,QAAbA,MAAa;AACzE,MAAMI,IAAI,GAAGL,SAAS,GAAGM,iBAAH,GAAWC,iBAAjC;AACA,MAAMC,eAAe,GAAGR,SAAS,KAAKS,SAAtC;AACA,MAAMC,WAAW,GAAGF,eAAe,GAAGT,mBAAmB,CAACC,SAAD,EAAYC,MAAZ,CAAtB,GAA4C,EAA/E;AAEA,SAAOO,eAAe,gBAAG,gCAAC,IAAD;AAAM,IAAA,SAAS,YAAKL,OAAO,CAACQ,IAAb,cAAqBR,OAAO,CAACO,WAAD,CAA5B,CAAf;AAA4D,IAAA,KAAK,EAAEN;AAAnE,IAAH,GAA2F,IAAjH;AACD,CAND;;AAQAF,cAAc,CAACU,SAAf,GAA2B;AACzBT,EAAAA,OAAO,EAAEU,sBAAUC,MADM;AAEzBV,EAAAA,cAAc,EAAES,sBAAUC,MAFD;AAGzBb,EAAAA,MAAM,EAAEY,sBAAUE,IAHO;AAIzBf,EAAAA,SAAS,EAAEa,sBAAUG,SAAV,CAAoB,CAACH,sBAAUE,IAAX,EAAiBF,sBAAUI,MAA3B,CAApB;AAJc,CAA3B;AAOAf,cAAc,CAACgB,YAAf,GAA8B;AAC5Bf,EAAAA,OAAO,EAAE,EADmB;AAE5BC,EAAAA,cAAc,EAAE,EAFY;AAG5BH,EAAAA,MAAM,EAAE,KAHoB;AAI5BD,EAAAA,SAAS,EAAES;AAJiB,CAA9B;;AAOA,IAAMU,MAAM,GAAG,SAATA,MAAS;AAAA,SAAO;AACpBC,IAAAA,YAAY,EAAE;AACZC,MAAAA,KAAK,EAAEA,gBAAMC,OAAN;AADK,KADM;AAIpBC,IAAAA,aAAa,EAAE;AACbF,MAAAA,KAAK,EAAEA,gBAAMG,UAAN,EADM;AAEbC,MAAAA,eAAe,EAAEJ,gBAAMC,OAAN;AAFJ,KAJK;AAQpBI,IAAAA,cAAc,EAAE;AACdL,MAAAA,KAAK,EAAEA,gBAAMM,SAAN;AADO,KARI;AAWpBC,IAAAA,eAAe,EAAE;AACfP,MAAAA,KAAK,EAAEA,gBAAMG,UAAN,EADQ;AAEfC,MAAAA,eAAe,EAAEJ,gBAAMM,SAAN;AAFF;AAXG,GAAP;AAAA,CAAf;;eAiBe,sBAAWR,MAAX,EAAmBjB,cAAnB,C","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core';\nimport Check from '@material-ui/icons/Check';\nimport Close from '@material-ui/icons/Close';\nimport { color } from '@pie-lib/render-ui';\n\nconst getCorrectnessClass = (isCorrect, filled) => {\n if (filled) {\n return isCorrect ? 'correctFilled' : 'incorrectFilled';\n }\n return isCorrect ? 'correctEmpty' : 'incorrectEmpty';\n};\n\nconst EvaluationIcon = ({ classes, containerStyle, isCorrect, filled }) => {\n const Icon = isCorrect ? Check : Close;\n const showCorrectness = isCorrect !== undefined;\n const correctness = showCorrectness ? getCorrectnessClass(isCorrect, filled) : '';\n\n return showCorrectness ? <Icon className={`${classes.icon} ${classes[correctness]}`} style={containerStyle} /> : null;\n};\n\nEvaluationIcon.propTypes = {\n classes: PropTypes.object,\n containerStyle: PropTypes.object,\n filled: PropTypes.bool,\n isCorrect: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),\n};\n\nEvaluationIcon.defaultProps = {\n classes: {},\n containerStyle: {},\n filled: false,\n isCorrect: undefined,\n};\n\nconst styles = () => ({\n correctEmpty: {\n color: color.correct(),\n },\n correctFilled: {\n color: color.background(),\n backgroundColor: color.correct(),\n },\n incorrectEmpty: {\n color: color.incorrect(),\n },\n incorrectFilled: {\n color: color.background(),\n backgroundColor: color.incorrect(),\n },\n});\n\nexport default withStyles(styles)(EvaluationIcon);\n"],"file":"evaluation-icon.js"}
|