@pie-element/placement-ordering 12.0.2-esm.0 → 12.2.0

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/esm/controller.js DELETED
@@ -1,924 +0,0 @@
1
- import _ from 'lodash';
2
- import debug from 'debug';
3
- import { getFeedbackForCorrectness } from '@pie-lib/feedback';
4
- import { partialScoring } from '@pie-lib/controller-utils';
5
- import isEqual from 'lodash/isEqual';
6
- import isEmpty from 'lodash/isEmpty';
7
- import Translator from '@pie-lib/translator';
8
-
9
- function _extends() {
10
- _extends = Object.assign || function (target) {
11
- for (var i = 1; i < arguments.length; i++) {
12
- var source = arguments[i];
13
-
14
- for (var key in source) {
15
- if (Object.prototype.hasOwnProperty.call(source, key)) {
16
- target[key] = source[key];
17
- }
18
- }
19
- }
20
-
21
- return target;
22
- };
23
-
24
- return _extends.apply(this, arguments);
25
- }
26
-
27
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
28
-
29
- var combinatorics = {exports: {}};
30
-
31
- /*
32
- * $Id: combinatorics.js,v 0.25 2013/03/11 15:42:14 dankogai Exp dankogai $
33
- *
34
- * Licensed under the MIT license.
35
- * http://www.opensource.org/licenses/mit-license.php
36
- *
37
- * References:
38
- * http://www.ruby-doc.org/core-2.0/Array.html#method-i-combination
39
- * http://www.ruby-doc.org/core-2.0/Array.html#method-i-permutation
40
- * http://en.wikipedia.org/wiki/Factorial_number_system
41
- */
42
-
43
- (function (module, exports) {
44
- (function (root, factory) {
45
- {
46
- module.exports = factory();
47
- }
48
- }(commonjsGlobal, function () {
49
- var version = "0.5.5";
50
- /* combinatory arithmetics */
51
- var P = function(m, n) {
52
- if (n % 1 !== 0) throw new RangeError;
53
- var p = 1;
54
- while (n--) p *= m--;
55
- return p;
56
- };
57
- var C = function(m, n) {
58
- if (n > m) {
59
- return 0;
60
- }
61
- return P(m, n) / P(n, n);
62
- };
63
- var factorial = function(n) {
64
- return P(n, n);
65
- };
66
- var factoradic = function(n, d) {
67
- var f = 1;
68
- if (!d) {
69
- for (d = 1; f < n; f *= ++d);
70
- if (f > n) f /= d--;
71
- } else {
72
- f = factorial(d);
73
- }
74
- var result = [0];
75
- for (; d; f /= d--) {
76
- result[d] = Math.floor(n / f);
77
- n %= f;
78
- }
79
- return result;
80
- };
81
- /* common methods */
82
- var addProperties = function(dst, src) {
83
- Object.keys(src).forEach(function(p) {
84
- Object.defineProperty(dst, p, {
85
- value: src[p],
86
- configurable: p == 'next'
87
- });
88
- });
89
- };
90
- var hideProperty = function(o, p) {
91
- Object.defineProperty(o, p, {
92
- writable: true
93
- });
94
- };
95
- var toArray = function(f) {
96
- var e, result = [];
97
- this.init();
98
- while (e = this.next()) result.push(f ? f(e) : e);
99
- this.init();
100
- return result;
101
- };
102
- var common = {
103
- toArray: toArray,
104
- map: toArray,
105
- forEach: function(f) {
106
- var e;
107
- this.init();
108
- while (e = this.next()) f(e);
109
- this.init();
110
- },
111
- filter: function(f) {
112
- var e, result = [];
113
- this.init();
114
- while (e = this.next()) if (f(e)) result.push(e);
115
- this.init();
116
- return result;
117
- },
118
- find: function(f) {
119
- var e, result;
120
- this.init();
121
- while (e = this.next()) {
122
- if (f(e)) {
123
- result = e;
124
- break;
125
- }
126
- }
127
- this.init();
128
- return result;
129
- },
130
- reduce: function(reducer, result) {
131
- // return this.toArray().reduce(reducer, init);
132
- this.init();
133
- var index = 0;
134
- if (arguments.length < 2) {
135
- result = this.next();
136
- index += 1;
137
- }
138
- var length = this.length;
139
- while(index < length) {
140
- result = reducer(result, this.next(), index, this);
141
- index += 1;
142
- }
143
- return result;
144
- },
145
- lazyMap: function(f) {
146
- this._lazyMap = f;
147
- return this;
148
- },
149
- lazyFilter: function(f) {
150
- Object.defineProperty(this, 'next', {
151
- writable: true
152
- });
153
- if (typeof f !== 'function') {
154
- this.next = this._next;
155
- } else {
156
- if (typeof (this._next) !== 'function') {
157
- this._next = this.next;
158
- }
159
- var _next = this._next.bind(this);
160
- this.next = (function() {
161
- var e;
162
- while (e = _next()) {
163
- if (f(e))
164
- return e;
165
- }
166
- return e;
167
- }).bind(this);
168
- }
169
- Object.defineProperty(this, 'next', {
170
- writable: false
171
- });
172
- return this;
173
- }
174
-
175
- };
176
- /* power set */
177
- var power = function(ary, fun) {
178
- var size = 1 << ary.length,
179
- sizeOf = function() {
180
- return size;
181
- },
182
- that = Object.create(ary.slice(), {
183
- length: {
184
- get: sizeOf
185
- }
186
- });
187
- hideProperty(that, 'index');
188
- addProperties(that, {
189
- valueOf: sizeOf,
190
- init: function() {
191
- that.index = 0;
192
- },
193
- nth: function(n) {
194
- if (n >= size) return;
195
- var i = 0,
196
- result = [];
197
- for (; n; n >>>= 1, i++) if (n & 1) result.push(this[i]);
198
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
199
- },
200
- next: function() {
201
- return this.nth(this.index++);
202
- }
203
- });
204
- addProperties(that, common);
205
- that.init();
206
- return (typeof (fun) === 'function') ? that.map(fun) : that;
207
- };
208
- /* combination */
209
- var nextIndex = function(n) {
210
- var smallest = n & -n,
211
- ripple = n + smallest,
212
- new_smallest = ripple & -ripple,
213
- ones = ((new_smallest / smallest) >> 1) - 1;
214
- return ripple | ones;
215
- };
216
- var combination = function(ary, nelem, fun) {
217
- if (!nelem) nelem = ary.length;
218
- if (nelem < 1) throw new RangeError;
219
- if (nelem > ary.length) throw new RangeError;
220
- var first = (1 << nelem) - 1,
221
- size = C(ary.length, nelem),
222
- maxIndex = 1 << ary.length,
223
- sizeOf = function() {
224
- return size;
225
- },
226
- that = Object.create(ary.slice(), {
227
- length: {
228
- get: sizeOf
229
- }
230
- });
231
- hideProperty(that, 'index');
232
- addProperties(that, {
233
- valueOf: sizeOf,
234
- init: function() {
235
- this.index = first;
236
- },
237
- next: function() {
238
- if (this.index >= maxIndex) return;
239
- var i = 0,
240
- n = this.index,
241
- result = [];
242
- for (; n; n >>>= 1, i++) {
243
- if (n & 1) result[result.length] = this[i];
244
- }
245
-
246
- this.index = nextIndex(this.index);
247
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
248
- }
249
- });
250
- addProperties(that, common);
251
- that.init();
252
- return (typeof (fun) === 'function') ? that.map(fun) : that;
253
- };
254
- /* bigcombination */
255
- var bigNextIndex = function(n, nelem) {
256
-
257
- var result = n;
258
- var j = nelem;
259
- var i = 0;
260
- for (i = result.length - 1; i >= 0; i--) {
261
- if (result[i] == 1) {
262
- j--;
263
- } else {
264
- break;
265
- }
266
- }
267
- if (j == 0) {
268
- // Overflow
269
- result[result.length] = 1;
270
- for (var k = result.length - 2; k >= 0; k--) {
271
- result[k] = (k < nelem-1)?1:0;
272
- }
273
- } else {
274
- // Normal
275
-
276
- // first zero after 1
277
- var i1 = -1;
278
- var i0 = -1;
279
- for (var i = 0; i < result.length; i++) {
280
- if (result[i] == 0 && i1 != -1) {
281
- i0 = i;
282
- }
283
- if (result[i] == 1) {
284
- i1 = i;
285
- }
286
- if (i0 != -1 && i1 != -1) {
287
- result[i0] = 1;
288
- result[i1] = 0;
289
- break;
290
- }
291
- }
292
-
293
- j = nelem;
294
- for (var i = result.length - 1; i >= i1; i--) {
295
- if (result[i] == 1)
296
- j--;
297
- }
298
- for (var i = 0; i < i1; i++) {
299
- result[i] = (i < j)?1:0;
300
- }
301
- }
302
-
303
- return result;
304
-
305
- };
306
- var buildFirst = function(nelem) {
307
- var result = [];
308
- for (var i = 0; i < nelem; i++) {
309
- result[i] = 1;
310
- }
311
- result[0] = 1;
312
- return result;
313
- };
314
- var bigCombination = function(ary, nelem, fun) {
315
- if (!nelem) nelem = ary.length;
316
- if (nelem < 1) throw new RangeError;
317
- if (nelem > ary.length) throw new RangeError;
318
- var first = buildFirst(nelem),
319
- size = C(ary.length, nelem),
320
- maxIndex = ary.length,
321
- sizeOf = function() {
322
- return size;
323
- },
324
- that = Object.create(ary.slice(), {
325
- length: {
326
- get: sizeOf
327
- }
328
- });
329
- hideProperty(that, 'index');
330
- addProperties(that, {
331
- valueOf: sizeOf,
332
- init: function() {
333
- this.index = first.concat();
334
- },
335
- next: function() {
336
- if (this.index.length > maxIndex) return;
337
- var i = 0,
338
- n = this.index,
339
- result = [];
340
- for (var j = 0; j < n.length; j++, i++) {
341
- if (n[j])
342
- result[result.length] = this[i];
343
- }
344
- bigNextIndex(this.index, nelem);
345
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
346
- }
347
- });
348
- addProperties(that, common);
349
- that.init();
350
- return (typeof (fun) === 'function') ? that.map(fun) : that;
351
- };
352
- /* permutation */
353
- var _permutation = function(ary) {
354
- var that = ary.slice(),
355
- size = factorial(that.length);
356
- that.index = 0;
357
- that.next = function() {
358
- if (this.index >= size) return;
359
- var copy = this.slice(),
360
- digits = factoradic(this.index, this.length),
361
- result = [],
362
- i = this.length - 1;
363
- for (; i >= 0; --i) result.push(copy.splice(digits[i], 1)[0]);
364
- this.index++;
365
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
366
- };
367
- return that;
368
- };
369
- // which is really a permutation of combination
370
- var permutation = function(ary, nelem, fun) {
371
- if (!nelem) nelem = ary.length;
372
- if (nelem < 1) throw new RangeError;
373
- if (nelem > ary.length) throw new RangeError;
374
- var size = P(ary.length, nelem),
375
- sizeOf = function() {
376
- return size;
377
- },
378
- that = Object.create(ary.slice(), {
379
- length: {
380
- get: sizeOf
381
- }
382
- });
383
- hideProperty(that, 'cmb');
384
- hideProperty(that, 'per');
385
- addProperties(that, {
386
- valueOf: function() {
387
- return size;
388
- },
389
- init: function() {
390
- /* combination can only be used for less than 31 elements */
391
- if (ary.length < 31) {
392
- this.cmb = combination(ary, nelem);
393
- } else {
394
- this.cmb = bigCombination(ary, nelem);
395
- }
396
-
397
- this.per = _permutation(this.cmb.next());
398
- },
399
- next: function() {
400
- var result = this.per.next();
401
- if (!result) {
402
- var cmb = this.cmb.next();
403
- if (!cmb) return;
404
- this.per = _permutation(cmb);
405
- return this.next();
406
- }
407
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
408
- }
409
- });
410
- addProperties(that, common);
411
- that.init();
412
- return (typeof (fun) === 'function') ? that.map(fun) : that;
413
- };
414
-
415
- var PC = function(m) {
416
- var total = 0;
417
- for (var n = 1; n <= m; n++) {
418
- var p = P(m,n);
419
- total += p;
420
- } return total;
421
- };
422
- // which is really a permutation of combination
423
- var permutationCombination = function(ary, fun) {
424
- // if (!nelem) nelem = ary.length;
425
- // if (nelem < 1) throw new RangeError;
426
- // if (nelem > ary.length) throw new RangeError;
427
- var size = PC(ary.length),
428
- sizeOf = function() {
429
- return size;
430
- },
431
- that = Object.create(ary.slice(), {
432
- length: {
433
- get: sizeOf
434
- }
435
- });
436
- hideProperty(that, 'cmb');
437
- hideProperty(that, 'per');
438
- hideProperty(that, 'nelem');
439
- addProperties(that, {
440
- valueOf: function() {
441
- return size;
442
- },
443
- init: function() {
444
- this.nelem = 1;
445
- // console.log("Starting nelem: " + this.nelem);
446
- this.cmb = combination(ary, this.nelem);
447
- this.per = _permutation(this.cmb.next());
448
- },
449
- next: function() {
450
- var result = this.per.next();
451
- if (!result) {
452
- var cmb = this.cmb.next();
453
- if (!cmb) {
454
- this.nelem++;
455
- // console.log("increment nelem: " + this.nelem + " vs " + ary.length);
456
- if (this.nelem > ary.length) return;
457
- this.cmb = combination(ary, this.nelem);
458
- cmb = this.cmb.next();
459
- if (!cmb) return;
460
- }
461
- this.per = _permutation(cmb);
462
- return this.next();
463
- }
464
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
465
- }
466
- });
467
- addProperties(that, common);
468
- that.init();
469
- return (typeof (fun) === 'function') ? that.map(fun) : that;
470
- };
471
- /* Cartesian Product */
472
- var arraySlice = Array.prototype.slice;
473
- var cartesianProduct = function() {
474
- if (!arguments.length) throw new RangeError;
475
- var args = arraySlice.call(arguments),
476
- size = args.reduce(function(p, a) {
477
- return p * a.length;
478
- }, 1),
479
- sizeOf = function() {
480
- return size;
481
- },
482
- dim = args.length,
483
- that = Object.create(args, {
484
- length: {
485
- get: sizeOf
486
- }
487
- });
488
- if (!size) throw new RangeError;
489
- hideProperty(that, 'index');
490
- addProperties(that, {
491
- valueOf: sizeOf,
492
- dim: dim,
493
- init: function() {
494
- this.index = 0;
495
- },
496
- get: function() {
497
- if (arguments.length !== this.length) return;
498
- var result = [],
499
- d = 0;
500
- for (; d < dim; d++) {
501
- var i = arguments[d];
502
- if (i >= this[d].length) return;
503
- result.push(this[d][i]);
504
- }
505
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
506
- },
507
- nth: function(n) {
508
- var result = [],
509
- d = 0;
510
- for (; d < dim; d++) {
511
- var l = this[d].length;
512
- var i = n % l;
513
- result.push(this[d][i]);
514
- n -= i;
515
- n /= l;
516
- }
517
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
518
- },
519
- next: function() {
520
- if (this.index >= size) return;
521
- var result = this.nth(this.index);
522
- this.index++;
523
- return result;
524
- }
525
- });
526
- addProperties(that, common);
527
- that.init();
528
- return that;
529
- };
530
- /* baseN */
531
- var baseN = function(ary, nelem, fun) {
532
- if (!nelem) nelem = ary.length;
533
- if (nelem < 1) throw new RangeError;
534
- var base = ary.length,
535
- size = Math.pow(base, nelem);
536
- var sizeOf = function() {
537
- return size;
538
- },
539
- that = Object.create(ary.slice(), {
540
- length: {
541
- get: sizeOf
542
- }
543
- });
544
- hideProperty(that, 'index');
545
- addProperties(that, {
546
- valueOf: sizeOf,
547
- init: function() {
548
- that.index = 0;
549
- },
550
- nth: function(n) {
551
- if (n >= size) return;
552
- var result = [];
553
- for (var i = 0; i < nelem; i++) {
554
- var d = n % base;
555
- result.push(ary[d]);
556
- n -= d; n /= base;
557
- }
558
- return (typeof (that._lazyMap) === 'function')?that._lazyMap(result):result;
559
- },
560
- next: function() {
561
- return this.nth(this.index++);
562
- }
563
- });
564
- addProperties(that, common);
565
- that.init();
566
- return (typeof (fun) === 'function') ? that.map(fun) : that;
567
- };
568
-
569
- /* export */
570
- var Combinatorics = Object.create(null);
571
- addProperties(Combinatorics, {
572
- C: C,
573
- P: P,
574
- factorial: factorial,
575
- factoradic: factoradic,
576
- cartesianProduct: cartesianProduct,
577
- combination: combination,
578
- bigCombination: bigCombination,
579
- permutation: permutation,
580
- permutationCombination: permutationCombination,
581
- power: power,
582
- baseN: baseN,
583
- VERSION: version
584
- });
585
- return Combinatorics;
586
- }));
587
- }(combinatorics));
588
-
589
- const log$1 = debug('pie-elements:placement-ordering:controller');
590
- const illegalArgumentError = answer => new Error(`Cant score answer: ${answer} it has duplicates and allowDuplicates is false`);
591
- const pairwiseCombinationScore = (correct, answer, opts) => {
592
- opts = _extends({
593
- allowDuplicates: false,
594
- orderMustBeComplete: false
595
- }, opts);
596
-
597
- if (!opts.allowDuplicates && !_.isEqual(_.uniq(correct), correct)) {
598
- throw illegalArgumentError(answer);
599
- }
600
-
601
- if (opts.allowDuplicates === false && answer.length !== _.uniq(answer).length) {
602
- return 0;
603
- }
604
-
605
- answer = opts.allowDuplicates !== false ? answer : _.uniq(answer);
606
- log$1('answer:', answer);
607
-
608
- if (!Array.isArray(correct) || correct.length === 0) {
609
- throw new Error('correct must be non empty an array');
610
- }
611
-
612
- if (correct.length === 1) {
613
- return _.isEqual(correct, answer) ? 1 : 0;
614
- }
615
-
616
- if (!Array.isArray(answer) || answer.length < 2) {
617
- return 0;
618
- }
619
-
620
- if (answer.length > correct.length) {
621
- return 0;
622
- }
623
-
624
- if (correct.length !== answer.length && opts.orderMustBeComplete) {
625
- return 0;
626
- }
627
-
628
- const correctCombo = combinatorics.exports.combination(correct, 2).toArray();
629
- const answerCombo = combinatorics.exports.combination(answer, 2).toArray();
630
-
631
- const diff = _.differenceWith(answerCombo, correctCombo, _.isEqual);
632
-
633
- const comboLengthDiff = correctCombo.length - answerCombo.length;
634
- const total = correctCombo.length;
635
- const actual = total - diff.length - comboLengthDiff;
636
- const n = (actual / total).toFixed(2);
637
- return parseFloat(n);
638
- };
639
- /**
640
- * Flattens the correctResponse into an array of ordered identifiers representing the
641
- * correct response.
642
- */
643
-
644
- const flattenCorrect = question => question.correctResponse ? question.correctResponse.map(r => r && r.id ? r.id : r) : [];
645
- /**
646
- * Returns all correct responses for this question
647
- * @param question - array
648
- */
649
-
650
- const getAllCorrectResponses = question => {
651
- const alternates = (question.alternateResponses || []).map(alternate => {
652
- if (Array.isArray(alternate)) {
653
- return alternate;
654
- }
655
-
656
- return alternate.response;
657
- }).filter(item => item !== undefined);
658
- return [flattenCorrect(question), ...alternates];
659
- };
660
- /**
661
- * Returns the score for a session. If weighted scoring is present in the correctResponse
662
- * field for the question, this will be used. If partial scoring is present in the question
663
- * model, this will be used. Otherwise the default scoring mechanism (0 for any incorrect, 1
664
- * for all correct) will be used.
665
- */
666
-
667
- const score = (question, session) => {
668
- const {
669
- value
670
- } = session || {};
671
-
672
- if (!value) {
673
- return 0;
674
- }
675
-
676
- const allCorrectResponse = getAllCorrectResponses(question);
677
- const allowDuplicates = (question.configure && question.configure.removeTilesAfterPlacing) !== false;
678
- /**
679
- * We require this to be the case - locking
680
- */
681
- //const orderMustBeComplete = true;
682
-
683
- let bestScore = 0;
684
- allCorrectResponse.forEach(cr => {
685
- const currentScore = pairwiseCombinationScore(cr, value, {
686
- allowDuplicates
687
- });
688
-
689
- if (currentScore >= bestScore) {
690
- bestScore = currentScore;
691
- }
692
- });
693
- return bestScore;
694
- };
695
-
696
- var defaults = {
697
- choiceLabel: '',
698
- choiceLabelEnabled: true,
699
- choices: [],
700
- correctResponse: [],
701
- feedbackEnabled: false,
702
- numberedGuides: false,
703
- orientation: 'vertical',
704
- partialScoring: true,
705
- placementArea: false,
706
- prompt: '',
707
- promptEnabled: true,
708
- rationale: '',
709
- rationaleEnabled: true,
710
- removeTilesAfterPlacing: true,
711
- scoringType: 'auto',
712
- studentInstructionsEnabled: true,
713
- targetLabel: '',
714
- teacherInstructions: '',
715
- teacherInstructionsEnabled: true,
716
- toolbarEditorPosition: 'bottom'
717
- };
718
-
719
- const log = debug('@pie-element:placement-ordering:controller');
720
- const {
721
- translator
722
- } = Translator;
723
- const questionError = () => new Error('Question is missing required array: correctResponse');
724
- function outcome(question, session, env) {
725
- return new Promise((resolve, reject) => {
726
- if (!session || _.isEmpty(session)) {
727
- resolve({
728
- score: 0,
729
- empty: true
730
- });
731
- }
732
-
733
- if (!question || !question.correctResponse || _.isEmpty(question.correctResponse)) {
734
- reject(questionError());
735
- } else {
736
- try {
737
- const s = score(question, session);
738
- const finalScore = partialScoring.enabled(question, env || {}) ? s : s === 1 ? 1 : 0;
739
- resolve({
740
- score: finalScore
741
- });
742
- } catch (e) {
743
- reject(e);
744
- }
745
- }
746
- });
747
- }
748
- function createDefaultModel(model = {}) {
749
- return new Promise(resolve => {
750
- resolve(_extends({}, defaults, model));
751
- });
752
- }
753
- const normalize = question => _extends({}, defaults, {
754
- rationaleEnabled: true,
755
- feedbackEnabled: false,
756
- promptEnabled: true,
757
- teacherInstructionsEnabled: true,
758
- studentInstructionsEnabled: true
759
- }, question);
760
- /**
761
- *
762
- * @param {*} question
763
- * @param {*} session
764
- * @param {*} env
765
- */
766
-
767
- function model(question, session, env) {
768
- return new Promise(async resolve => {
769
- const normalizedQuestion = normalize(question);
770
- const base = {};
771
-
772
- if (question.alternateResponses && _.every(question.alternateResponses, _.isArray)) {
773
- log('Deprecated structure of alternateResponses is in use'); // eslint-disable-next-line no-console
774
-
775
- console.error('Deprecated structure of alternateResponses is in use');
776
- }
777
-
778
- base.env = env;
779
- base.extraCSSRules = normalizedQuestion.extraCSSRules;
780
- base.outcomes = [];
781
- base.completeLength = (normalizedQuestion.correctResponse || []).length;
782
- base.choices = (normalizedQuestion.choices || []).filter(choice => choice.label);
783
- base.note = normalizedQuestion.note;
784
- base.showNote = normalizedQuestion.alternateResponses && normalizedQuestion.alternateResponses.length > 0;
785
- base.language = normalizedQuestion.language;
786
- log('[model] removing tileSize for the moment.');
787
- base.prompt = normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null;
788
- base.config = {
789
- orientation: normalizedQuestion.orientation || 'vertical',
790
- includeTargets: normalizedQuestion.placementArea,
791
- choiceLabelEnabled: normalizedQuestion.choiceLabelEnabled,
792
- targetLabel: normalizedQuestion.targetLabel,
793
- choiceLabel: normalizedQuestion.choiceLabel,
794
- showOrdering: normalizedQuestion.numberedGuides,
795
- allowSameChoiceInTargets: !normalizedQuestion.removeTilesAfterPlacing
796
- };
797
- base.disabled = env.mode !== 'gather';
798
-
799
- if (!base.note) {
800
- base.note = translator.t('common:commonCorrectAnswerWithAlternates', {
801
- lng: normalizedQuestion.language
802
- });
803
- }
804
-
805
- if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
806
- base.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;
807
- base.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;
808
- } else {
809
- base.rationale = null;
810
- base.teacherInstructions = null;
811
- }
812
-
813
- if (env.mode === 'evaluate') {
814
- const value = session && session.value || [];
815
- const allCorrectResponses = getAllCorrectResponses(normalizedQuestion);
816
- const bestSetOfResponses = allCorrectResponses.reduce((info, cr) => {
817
- const currentScore = _.reduce(value, (acc, c, idx) => acc + (Array.isArray(cr) && cr[idx] === c ? 1 : 0), 0);
818
-
819
- if (currentScore > info.score) {
820
- return {
821
- arr: cr,
822
- score: currentScore
823
- };
824
- }
825
-
826
- return info;
827
- }, {
828
- arr: [],
829
- score: 0
830
- });
831
- base.outcomes = _.map(value, (c, idx) => {
832
- return {
833
- id: c,
834
- outcome: bestSetOfResponses.arr[idx] === c ? 'correct' : 'incorrect'
835
- };
836
- });
837
- const isResponseCorrect = allCorrectResponses.some(response => _.isEqual(response, value));
838
- const responseScore = score(question, session);
839
- const isCorrect = responseScore === 1;
840
- const isPartialCorrect = !isCorrect && partialScoring.enabled(normalizedQuestion, env || {}) && responseScore !== 0;
841
- base.correctness = isCorrect ? 'correct' : isPartialCorrect ? 'partial' : 'incorrect';
842
-
843
- if (!isResponseCorrect) {
844
- base.correctResponse = flattenCorrect(normalizedQuestion);
845
- } // requirement made in PD-2182
846
-
847
-
848
- if (!normalizedQuestion.feedback) {
849
- normalizedQuestion.feedbackEnabled = false;
850
- }
851
-
852
- const fb = normalizedQuestion.feedbackEnabled ? getFeedbackForCorrectness(base.correctness, normalizedQuestion.feedback) : Promise.resolve(undefined);
853
- fb.then(feedback => {
854
- base.feedback = feedback;
855
- resolve(base);
856
- });
857
- } else {
858
- resolve(base);
859
- }
860
- });
861
- }
862
- const createCorrectResponseSession = (question, env) => {
863
- return new Promise(resolve => {
864
- if (env.mode !== 'evaluate' && env.role === 'instructor') {
865
- resolve({
866
- id: '1',
867
- value: flattenCorrect(question)
868
- });
869
- } else {
870
- resolve(null);
871
- }
872
- });
873
- }; // remove all html tags
874
-
875
-
876
- const getContent = html => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
877
-
878
- const validate = (model = {}, config = {}) => {
879
- const {
880
- choices,
881
- correctResponse
882
- } = model;
883
- const errors = {};
884
- ['teacherInstructions', 'prompt', 'rationale'].forEach(field => {
885
- var _config$field;
886
-
887
- if ((_config$field = config[field]) != null && _config$field.required && !getContent(model[field])) {
888
- errors[field] = 'This field is required.';
889
- }
890
- });
891
- const reversedChoices = [...(choices || [])].reverse();
892
- const choicesErrors = {};
893
- reversedChoices.forEach((choice, index) => {
894
- const {
895
- id,
896
- label
897
- } = choice;
898
-
899
- if (!getContent(label)) {
900
- choicesErrors[id] = 'Content should not be empty.';
901
- } else {
902
- const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.label === label);
903
-
904
- if (identicalAnswer) {
905
- choicesErrors[id] = 'Content should be unique.';
906
- }
907
- }
908
- });
909
- const choicesIds = (choices || []).map(choice => choice.id);
910
- const correctResponseIds = (correctResponse || []).map(response => response.id || response);
911
-
912
- if (isEqual(choicesIds, correctResponseIds)) {
913
- errors.orderError = 'The correct ordering should not be identical to the initial ordering.';
914
- }
915
-
916
- if (!isEmpty(choicesErrors)) {
917
- errors.choicesErrors = choicesErrors;
918
- }
919
-
920
- return errors;
921
- };
922
-
923
- export { createCorrectResponseSession, createDefaultModel, model, normalize, outcome, questionError, validate };
924
- //# sourceMappingURL=controller.js.map