@pie-element/match 11.0.5-esm.1 → 11.1.2-next.1
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 +1083 -2579
- package/configure/CHANGELOG.md +928 -2260
- package/configure/lib/add-row.js +27 -73
- package/configure/lib/add-row.js.map +1 -1
- package/configure/lib/answer-config-block.js +262 -335
- package/configure/lib/answer-config-block.js.map +1 -1
- package/configure/lib/common.js +18 -33
- package/configure/lib/common.js.map +1 -1
- package/configure/lib/configure.js +330 -420
- package/configure/lib/configure.js.map +1 -1
- package/configure/lib/defaults.js +5 -4
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/general-config-block.js +123 -190
- package/configure/lib/general-config-block.js.map +1 -1
- package/configure/lib/index.js +117 -190
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/row.js +283 -373
- package/configure/lib/row.js.map +1 -1
- package/configure/lib/utils.js +4 -15
- package/configure/lib/utils.js.map +1 -1
- package/configure/package.json +15 -14
- package/controller/CHANGELOG.md +630 -1541
- package/controller/lib/defaults.js +2 -3
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +173 -301
- package/controller/lib/index.js.map +1 -1
- package/controller/package.json +6 -6
- package/lib/answer-grid.js +145 -242
- package/lib/answer-grid.js.map +1 -1
- package/lib/index.js +59 -108
- package/lib/index.js.map +1 -1
- package/lib/main.js +123 -191
- package/lib/main.js.map +1 -1
- package/package.json +15 -29
- package/esm/configure.js +0 -3936
- package/esm/configure.js.map +0 -1
- package/esm/controller.js +0 -428
- package/esm/controller.js.map +0 -1
- package/esm/element.js +0 -472
- package/esm/element.js.map +0 -1
package/esm/controller.js
DELETED
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
import isEqual from 'lodash/isEqual';
|
|
2
|
-
import isEmpty from 'lodash/isEmpty';
|
|
3
|
-
import cloneDeep from 'lodash/cloneDeep';
|
|
4
|
-
import { getFeedbackForCorrectness } from '@pie-lib/feedback';
|
|
5
|
-
import { lockChoices, getShuffledChoices, partialScoring } from '@pie-lib/controller-utils';
|
|
6
|
-
import debug from 'debug';
|
|
7
|
-
|
|
8
|
-
function _extends() {
|
|
9
|
-
_extends = Object.assign || function (target) {
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
|
|
13
|
-
for (var key in source) {
|
|
14
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
15
|
-
target[key] = source[key];
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return target;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return _extends.apply(this, arguments);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
27
|
-
if (source == null) return {};
|
|
28
|
-
var target = {};
|
|
29
|
-
var sourceKeys = Object.keys(source);
|
|
30
|
-
var key, i;
|
|
31
|
-
|
|
32
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
|
33
|
-
key = sourceKeys[i];
|
|
34
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
35
|
-
target[key] = source[key];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return target;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
var defaults = {
|
|
42
|
-
choiceMode: 'radio',
|
|
43
|
-
feedbackEnabled: false,
|
|
44
|
-
headers: ['Column 1', 'Column 2', 'Column 3'],
|
|
45
|
-
layout: 3,
|
|
46
|
-
lockChoiceOrder: true,
|
|
47
|
-
partialScoring: false,
|
|
48
|
-
prompt: '',
|
|
49
|
-
promptEnabled: true,
|
|
50
|
-
rationale: '',
|
|
51
|
-
rationaleEnabled: true,
|
|
52
|
-
rows: [],
|
|
53
|
-
scoringType: 'auto',
|
|
54
|
-
studentInstructionsEnabled: true,
|
|
55
|
-
teacherInstructions: '',
|
|
56
|
-
teacherInstructionsEnabled: true,
|
|
57
|
-
toolbarEditorPosition: 'bottom'
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const _excluded = ["extraCSSRules", "feedbackEnabled", "promptEnabled", "prompt", "lockChoiceOrder"];
|
|
61
|
-
const log = debug('@pie-element:match:controller');
|
|
62
|
-
|
|
63
|
-
const getResponseCorrectness = (model, answers, env = {}) => {
|
|
64
|
-
const isPartialScoring = partialScoring.enabled(model, env);
|
|
65
|
-
const rows = model.rows;
|
|
66
|
-
const checkboxMode = model.choiceMode === 'checkbox';
|
|
67
|
-
|
|
68
|
-
if (!answers || Object.keys(answers).length === 0) {
|
|
69
|
-
return 'unanswered';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const totalCorrectAnswers = checkboxMode ? getTotalCorrectAnswers(model) : getTotalCorrect(model);
|
|
73
|
-
let correctAnswers;
|
|
74
|
-
let incorrectAnswers = 0;
|
|
75
|
-
|
|
76
|
-
if (checkboxMode) {
|
|
77
|
-
const checkboxes = getCheckboxes(rows, answers);
|
|
78
|
-
correctAnswers = checkboxes.correctAnswers;
|
|
79
|
-
incorrectAnswers = checkboxes.incorrectAnswers;
|
|
80
|
-
} else {
|
|
81
|
-
correctAnswers = getCorrectRadios(rows, answers);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (totalCorrectAnswers === correctAnswers && !incorrectAnswers) {
|
|
85
|
-
return 'correct';
|
|
86
|
-
} else if (correctAnswers === 0) {
|
|
87
|
-
return 'incorrect';
|
|
88
|
-
} else if (isPartialScoring) {
|
|
89
|
-
return 'partial';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return 'incorrect';
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const getCorrectness = (question, env, answers = {}) => {
|
|
96
|
-
if (env.mode === 'evaluate') {
|
|
97
|
-
return getResponseCorrectness(question, answers, env);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const getCheckboxes = (rows, answers) => {
|
|
102
|
-
let correctAnswers = 0;
|
|
103
|
-
let incorrectAnswers = 0;
|
|
104
|
-
rows.forEach(row => {
|
|
105
|
-
const answer = answers[row.id];
|
|
106
|
-
|
|
107
|
-
if (answer) {
|
|
108
|
-
row.values.forEach((v, i) => {
|
|
109
|
-
if (answer[i] && answer[i] === v) {
|
|
110
|
-
correctAnswers += 1;
|
|
111
|
-
} else if (answer[i] && answer[i] !== v) {
|
|
112
|
-
incorrectAnswers += 1;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
return {
|
|
118
|
-
correctAnswers,
|
|
119
|
-
incorrectAnswers
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const getCorrectRadios = (rows, answers) => {
|
|
124
|
-
let correctAnswers = 0;
|
|
125
|
-
rows.forEach(row => {
|
|
126
|
-
if (isEqual(row.values, answers[row.id])) {
|
|
127
|
-
correctAnswers += 1;
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
return correctAnswers;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const getTotalCorrect = question => {
|
|
134
|
-
const checkboxMode = question.choiceMode === 'checkbox';
|
|
135
|
-
const matchingTable = checkboxMode ? question.layout - 1 : 1;
|
|
136
|
-
return (question.rows.length || 0) * matchingTable;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
const getTotalCorrectAnswers = question => {
|
|
140
|
-
let noOfTotalCorrectAnswers = 0;
|
|
141
|
-
question.rows.forEach(row => {
|
|
142
|
-
row.values.forEach(value => {
|
|
143
|
-
if (value) {
|
|
144
|
-
noOfTotalCorrectAnswers += 1;
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
return noOfTotalCorrectAnswers;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
const getPartialScore = (question, answers) => {
|
|
152
|
-
const checkboxMode = question.choiceMode === 'checkbox';
|
|
153
|
-
|
|
154
|
-
if (checkboxMode) {
|
|
155
|
-
const {
|
|
156
|
-
correctAnswers,
|
|
157
|
-
incorrectAnswers
|
|
158
|
-
} = getCheckboxes(question.rows, answers);
|
|
159
|
-
const totalCorrect = getTotalCorrectAnswers(question);
|
|
160
|
-
const total = totalCorrect === 0 ? 1 : totalCorrect;
|
|
161
|
-
|
|
162
|
-
if (correctAnswers + incorrectAnswers > totalCorrect) {
|
|
163
|
-
const extraAnswers = correctAnswers + incorrectAnswers - totalCorrect;
|
|
164
|
-
const score = parseFloat(((correctAnswers - extraAnswers) / total).toFixed(2));
|
|
165
|
-
return score < 0 ? 0 : score;
|
|
166
|
-
} else {
|
|
167
|
-
return parseFloat((correctAnswers / total).toFixed(2));
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
const correctAnswers = getCorrectRadios(question.rows, answers);
|
|
171
|
-
const totalCorrect = getTotalCorrect(question) === 0 ? 1 : getTotalCorrect(question);
|
|
172
|
-
return parseFloat((correctAnswers / totalCorrect).toFixed(2));
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const getOutComeScore = (question, env, answers = {}) => {
|
|
177
|
-
const correctness = getCorrectness(question, env, answers);
|
|
178
|
-
const isPartialScoring = partialScoring.enabled(question, env);
|
|
179
|
-
return correctness === 'correct' ? 1 : correctness === 'partial' && isPartialScoring ? getPartialScore(question, answers) : 0;
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const outcome = (question, session, env) => {
|
|
183
|
-
return new Promise(resolve => {
|
|
184
|
-
if (env.mode !== 'evaluate') {
|
|
185
|
-
resolve({
|
|
186
|
-
score: undefined,
|
|
187
|
-
completed: undefined
|
|
188
|
-
});
|
|
189
|
-
} else {
|
|
190
|
-
if (!session || isEmpty(session)) {
|
|
191
|
-
resolve({
|
|
192
|
-
score: 0,
|
|
193
|
-
empty: true
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const out = {
|
|
198
|
-
score: getOutComeScore(question, env, session.answers)
|
|
199
|
-
};
|
|
200
|
-
resolve(out);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
};
|
|
204
|
-
function createDefaultModel(model = {}) {
|
|
205
|
-
return new Promise(resolve => {
|
|
206
|
-
resolve(_extends({}, defaults, model));
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
const normalize = question => _extends({}, defaults, question);
|
|
210
|
-
/**
|
|
211
|
-
*
|
|
212
|
-
* @param {*} question
|
|
213
|
-
* @param {*} session
|
|
214
|
-
* @param {*} env
|
|
215
|
-
* @param {*} updateSession - optional - a function that will set the properties passed into it on the session.
|
|
216
|
-
*/
|
|
217
|
-
|
|
218
|
-
function model(question, session, env, updateSession) {
|
|
219
|
-
return new Promise(async resolve => {
|
|
220
|
-
const normalizedQuestion = cloneDeep(normalize(question));
|
|
221
|
-
let correctness, score;
|
|
222
|
-
|
|
223
|
-
if ((!session || isEmpty(session)) && env.mode === 'evaluate') {
|
|
224
|
-
correctness = 'unanswered';
|
|
225
|
-
score = '0%';
|
|
226
|
-
} else {
|
|
227
|
-
correctness = getCorrectness(normalizedQuestion, env, session && session.answers);
|
|
228
|
-
score = `${getOutComeScore(normalizedQuestion, env, session && session.answers) * 100}%`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const correctResponse = {};
|
|
232
|
-
const correctInfo = {
|
|
233
|
-
score,
|
|
234
|
-
correctness
|
|
235
|
-
};
|
|
236
|
-
const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);
|
|
237
|
-
|
|
238
|
-
if (!lockChoiceOrder) {
|
|
239
|
-
normalizedQuestion.rows = await getShuffledChoices(normalizedQuestion.rows, session, updateSession, 'id');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
normalizedQuestion.rows.forEach(row => {
|
|
243
|
-
correctResponse[row.id] = row.values;
|
|
244
|
-
|
|
245
|
-
if (env.mode !== 'evaluate') {
|
|
246
|
-
delete row.values;
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
const fb = env.mode === 'evaluate' && normalizedQuestion.feedbackEnabled ? getFeedbackForCorrectness(correctInfo.correctness, normalizedQuestion.feedback) : Promise.resolve(undefined);
|
|
250
|
-
fb.then(feedback => {
|
|
251
|
-
const {
|
|
252
|
-
extraCSSRules,
|
|
253
|
-
feedbackEnabled,
|
|
254
|
-
promptEnabled,
|
|
255
|
-
prompt,
|
|
256
|
-
lockChoiceOrder
|
|
257
|
-
} = normalizedQuestion,
|
|
258
|
-
essentials = _objectWithoutPropertiesLoose(normalizedQuestion, _excluded);
|
|
259
|
-
|
|
260
|
-
const out = _extends({}, essentials, {
|
|
261
|
-
extraCSSRules,
|
|
262
|
-
allowFeedback: feedbackEnabled,
|
|
263
|
-
prompt: promptEnabled ? prompt : null,
|
|
264
|
-
shuffled: !lockChoiceOrder,
|
|
265
|
-
feedback,
|
|
266
|
-
disabled: env.mode !== 'gather',
|
|
267
|
-
view: env.mode === 'view'
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
271
|
-
out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;
|
|
272
|
-
out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;
|
|
273
|
-
} else {
|
|
274
|
-
out.rationale = null;
|
|
275
|
-
out.teacherInstructions = null;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (env.mode === 'evaluate') {
|
|
279
|
-
Object.assign(out, {
|
|
280
|
-
correctResponse,
|
|
281
|
-
correctness: correctInfo
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
log('out: ', out);
|
|
286
|
-
resolve(out);
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
const createCorrectResponseSession = (question, env) => {
|
|
291
|
-
return new Promise(resolve => {
|
|
292
|
-
if (env.mode !== 'evaluate' && env.role === 'instructor') {
|
|
293
|
-
const {
|
|
294
|
-
rows
|
|
295
|
-
} = question;
|
|
296
|
-
const answers = {};
|
|
297
|
-
rows.forEach(r => {
|
|
298
|
-
answers[r.id] = r.values;
|
|
299
|
-
});
|
|
300
|
-
resolve({
|
|
301
|
-
answers,
|
|
302
|
-
id: '1'
|
|
303
|
-
});
|
|
304
|
-
} else {
|
|
305
|
-
resolve(null);
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
}; // remove all html tags
|
|
309
|
-
|
|
310
|
-
const getInnerText = html => (html || '').replaceAll(/<[^>]*>/g, ''); // remove all html tags except img, iframe and source tag for audio
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const getContent = html => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
|
|
314
|
-
|
|
315
|
-
const validate = (model = {}, config = {}) => {
|
|
316
|
-
const {
|
|
317
|
-
rows,
|
|
318
|
-
choiceMode,
|
|
319
|
-
headers
|
|
320
|
-
} = model;
|
|
321
|
-
const {
|
|
322
|
-
minQuestions,
|
|
323
|
-
maxQuestions,
|
|
324
|
-
maxLengthQuestionsHeading,
|
|
325
|
-
maxAnswers,
|
|
326
|
-
maxLengthAnswers,
|
|
327
|
-
maxLengthFirstColumnHeading
|
|
328
|
-
} = config;
|
|
329
|
-
const rowsErrors = {};
|
|
330
|
-
const columnsErrors = {};
|
|
331
|
-
const errors = {};
|
|
332
|
-
['teacherInstructions', 'prompt', 'rationale'].forEach(field => {
|
|
333
|
-
var _config$field;
|
|
334
|
-
|
|
335
|
-
if ((_config$field = config[field]) != null && _config$field.required && !getContent(model[field])) {
|
|
336
|
-
errors[field] = 'This field is required.';
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
if (rows.length < minQuestions) {
|
|
341
|
-
errors.noOfRowsError = `There should be at least ${minQuestions} question rows.`;
|
|
342
|
-
} else if (rows.length > maxQuestions) {
|
|
343
|
-
errors.noOfRowsError = `No more than ${maxQuestions} question rows should be defined.`;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
(rows || []).forEach((row, index) => {
|
|
347
|
-
const {
|
|
348
|
-
id,
|
|
349
|
-
values = [],
|
|
350
|
-
title
|
|
351
|
-
} = row;
|
|
352
|
-
rowsErrors[id] = '';
|
|
353
|
-
|
|
354
|
-
if (maxLengthQuestionsHeading && getInnerText(title).length > maxLengthQuestionsHeading) {
|
|
355
|
-
rowsErrors[id] += `Content length should be maximum ${maxLengthQuestionsHeading} characters. `;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (!getContent(title)) {
|
|
359
|
-
rowsErrors[id] += 'Content should not be empty. ';
|
|
360
|
-
} else {
|
|
361
|
-
// check for identical content with the previous answers
|
|
362
|
-
const identicalAnswer = rows.slice(0, index).some(r => getContent(r.title) === getContent(title));
|
|
363
|
-
|
|
364
|
-
if (identicalAnswer) {
|
|
365
|
-
rowsErrors[id] += 'Content should be unique. ';
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const hasCorrectResponse = values.some(value => !!value);
|
|
370
|
-
|
|
371
|
-
if (!hasCorrectResponse) {
|
|
372
|
-
rowsErrors[id] += 'No correct response defined.';
|
|
373
|
-
}
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
if (maxAnswers && headers.length - 1 > maxAnswers) {
|
|
377
|
-
errors.columnsLengthError = `There should be maximum ${maxAnswers} answers.`;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (maxLengthFirstColumnHeading && headers[0].length > maxLengthFirstColumnHeading) {
|
|
381
|
-
columnsErrors[0] = `Content length should be maximum ${maxLengthFirstColumnHeading} characters.`;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const headersContent = (headers || []).map(heading => getContent(heading));
|
|
385
|
-
headersContent.shift(); // remove first column since it does not require validation
|
|
386
|
-
|
|
387
|
-
headersContent.forEach((heading, index) => {
|
|
388
|
-
const headerIndex = index + 1; // we need to add 1 because we removed first header from validation
|
|
389
|
-
|
|
390
|
-
columnsErrors[headerIndex] = '';
|
|
391
|
-
|
|
392
|
-
if (maxLengthAnswers && getInnerText(heading).length > maxLengthAnswers) {
|
|
393
|
-
columnsErrors[headerIndex] += `Content length should be maximum ${maxLengthAnswers} characters. `;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (!heading) {
|
|
397
|
-
columnsErrors[headerIndex] += 'Content should not be empty.';
|
|
398
|
-
} else {
|
|
399
|
-
// check for identical content with the previous headers
|
|
400
|
-
const identicalAnswer = headersContent.slice(0, index).some(head => head === heading);
|
|
401
|
-
|
|
402
|
-
if (identicalAnswer) {
|
|
403
|
-
columnsErrors[index + 1] += 'Content should be unique.';
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
const hasRowErrors = Object.values(rowsErrors).some(error => (error || '').length);
|
|
408
|
-
|
|
409
|
-
if (hasRowErrors) {
|
|
410
|
-
errors.rowsErrors = rowsErrors;
|
|
411
|
-
const noCorrectAnswer = Object.values(rowsErrors).some(error => (error || '').includes('No correct response defined.'));
|
|
412
|
-
|
|
413
|
-
if (noCorrectAnswer) {
|
|
414
|
-
errors.correctResponseError = choiceMode === 'radio' ? 'There should be a correct response defined for every row.' : 'There should be at least one correct response defined for every row.';
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const hasColumnErrors = Object.values(columnsErrors).some(error => (error || '').length);
|
|
419
|
-
|
|
420
|
-
if (hasColumnErrors) {
|
|
421
|
-
errors.columnsErrors = columnsErrors;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return errors;
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
export { createCorrectResponseSession, createDefaultModel, model, normalize, outcome, validate };
|
|
428
|
-
//# sourceMappingURL=controller.js.map
|
package/esm/controller.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"controller.js","sources":["../controller/src/defaults.js","../controller/src/index.js"],"sourcesContent":["export default {\n choiceMode: 'radio',\n feedbackEnabled: false,\n headers: ['Column 1', 'Column 2', 'Column 3'],\n layout: 3,\n lockChoiceOrder: true,\n partialScoring: false,\n prompt: '',\n promptEnabled: true,\n rationale: '',\n rationaleEnabled: true,\n rows: [],\n scoringType: 'auto',\n studentInstructionsEnabled: true,\n teacherInstructions: '',\n teacherInstructionsEnabled: true,\n toolbarEditorPosition: 'bottom',\n};\n","import isEqual from 'lodash/isEqual';\nimport isEmpty from 'lodash/isEmpty';\nimport cloneDeep from 'lodash/cloneDeep';\nimport { getFeedbackForCorrectness } from '@pie-lib/feedback';\nimport { lockChoices, getShuffledChoices, partialScoring } from '@pie-lib/controller-utils';\nimport debug from 'debug';\n\nconst log = debug('@pie-element:match:controller');\n\nimport defaults from './defaults';\n\nconst getResponseCorrectness = (model, answers, env = {}) => {\n const isPartialScoring = partialScoring.enabled(model, env);\n const rows = model.rows;\n const checkboxMode = model.choiceMode === 'checkbox';\n\n if (!answers || Object.keys(answers).length === 0) {\n return 'unanswered';\n }\n\n const totalCorrectAnswers = checkboxMode ? getTotalCorrectAnswers(model) : getTotalCorrect(model);\n let correctAnswers;\n let incorrectAnswers = 0;\n\n if (checkboxMode) {\n const checkboxes = getCheckboxes(rows, answers);\n\n correctAnswers = checkboxes.correctAnswers;\n incorrectAnswers = checkboxes.incorrectAnswers;\n } else {\n correctAnswers = getCorrectRadios(rows, answers);\n }\n\n if (totalCorrectAnswers === correctAnswers && !incorrectAnswers) {\n return 'correct';\n } else if (correctAnswers === 0) {\n return 'incorrect';\n } else if (isPartialScoring) {\n return 'partial';\n }\n\n return 'incorrect';\n};\n\nconst getCorrectness = (question, env, answers = {}) => {\n if (env.mode === 'evaluate') {\n return getResponseCorrectness(question, answers, env);\n }\n};\n\nconst getCheckboxes = (rows, answers) => {\n let correctAnswers = 0;\n let incorrectAnswers = 0;\n\n rows.forEach((row) => {\n const answer = answers[row.id];\n\n if (answer) {\n row.values.forEach((v, i) => {\n if (answer[i] && answer[i] === v) {\n correctAnswers += 1;\n } else if (answer[i] && answer[i] !== v) {\n incorrectAnswers += 1;\n }\n });\n }\n });\n\n return { correctAnswers, incorrectAnswers };\n};\n\nconst getCorrectRadios = (rows, answers) => {\n let correctAnswers = 0;\n\n rows.forEach((row) => {\n if (isEqual(row.values, answers[row.id])) {\n correctAnswers += 1;\n }\n });\n\n return correctAnswers;\n};\n\nconst getTotalCorrect = (question) => {\n const checkboxMode = question.choiceMode === 'checkbox';\n const matchingTable = checkboxMode ? question.layout - 1 : 1;\n return (question.rows.length || 0) * matchingTable;\n};\n\nconst getTotalCorrectAnswers = (question) => {\n let noOfTotalCorrectAnswers = 0;\n\n question.rows.forEach((row) => {\n row.values.forEach((value) => {\n if (value) {\n noOfTotalCorrectAnswers += 1;\n }\n });\n });\n\n return noOfTotalCorrectAnswers;\n};\n\nconst getPartialScore = (question, answers) => {\n const checkboxMode = question.choiceMode === 'checkbox';\n\n if (checkboxMode) {\n const { correctAnswers, incorrectAnswers } = getCheckboxes(question.rows, answers);\n const totalCorrect = getTotalCorrectAnswers(question);\n\n const total = totalCorrect === 0 ? 1 : totalCorrect;\n\n if (correctAnswers + incorrectAnswers > totalCorrect) {\n const extraAnswers = correctAnswers + incorrectAnswers - totalCorrect;\n const score = parseFloat(((correctAnswers - extraAnswers) / total).toFixed(2));\n\n return score < 0 ? 0 : score;\n } else {\n return parseFloat((correctAnswers / total).toFixed(2));\n }\n } else {\n const correctAnswers = getCorrectRadios(question.rows, answers);\n const totalCorrect = getTotalCorrect(question) === 0 ? 1 : getTotalCorrect(question);\n\n return parseFloat((correctAnswers / totalCorrect).toFixed(2));\n }\n};\n\nconst getOutComeScore = (question, env, answers = {}) => {\n const correctness = getCorrectness(question, env, answers);\n const isPartialScoring = partialScoring.enabled(question, env);\n\n return correctness === 'correct'\n ? 1\n : correctness === 'partial' && isPartialScoring\n ? getPartialScore(question, answers)\n : 0;\n};\n\nexport const outcome = (question, session, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate') {\n resolve({ score: undefined, completed: undefined });\n } else {\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n const out = {\n score: getOutComeScore(question, env, session.answers),\n };\n\n resolve(out);\n }\n });\n};\n\nexport function createDefaultModel(model = {}) {\n return new Promise((resolve) => {\n resolve({\n ...defaults,\n ...model,\n });\n });\n}\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\n/**\n *\n * @param {*} question\n * @param {*} session\n * @param {*} env\n * @param {*} updateSession - optional - a function that will set the properties passed into it on the session.\n */\nexport function model(question, session, env, updateSession) {\n return new Promise(async (resolve) => {\n const normalizedQuestion = cloneDeep(normalize(question));\n let correctness, score;\n\n if ((!session || isEmpty(session)) && env.mode === 'evaluate') {\n correctness = 'unanswered';\n score = '0%';\n } else {\n correctness = getCorrectness(normalizedQuestion, env, session && session.answers);\n score = `${getOutComeScore(normalizedQuestion, env, session && session.answers) * 100}%`;\n }\n\n const correctResponse = {};\n const correctInfo = {\n score,\n correctness,\n };\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n if (!lockChoiceOrder) {\n normalizedQuestion.rows = await getShuffledChoices(normalizedQuestion.rows, session, updateSession, 'id');\n }\n\n normalizedQuestion.rows.forEach((row) => {\n correctResponse[row.id] = row.values;\n\n if (env.mode !== 'evaluate') {\n delete row.values;\n }\n });\n\n const fb =\n env.mode === 'evaluate' && normalizedQuestion.feedbackEnabled\n ? getFeedbackForCorrectness(correctInfo.correctness, normalizedQuestion.feedback)\n : Promise.resolve(undefined);\n\n fb.then((feedback) => {\n const { extraCSSRules, feedbackEnabled, promptEnabled, prompt, lockChoiceOrder, ...essentials } =\n normalizedQuestion;\n const out = {\n ...essentials,\n extraCSSRules,\n allowFeedback: feedbackEnabled,\n prompt: promptEnabled ? prompt : null,\n shuffled: !lockChoiceOrder,\n feedback,\n disabled: env.mode !== 'gather',\n view: env.mode === 'view',\n };\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled\n ? normalizedQuestion.teacherInstructions\n : null;\n out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n if (env.mode === 'evaluate') {\n Object.assign(out, {\n correctResponse,\n correctness: correctInfo,\n });\n }\n\n log('out: ', out);\n resolve(out);\n });\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { rows } = question;\n const answers = {};\n\n rows.forEach((r) => {\n answers[r.id] = r.values;\n });\n\n resolve({\n answers,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img, iframe and source tag for audio\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const { rows, choiceMode, headers } = model;\n const {\n minQuestions,\n maxQuestions,\n maxLengthQuestionsHeading,\n maxAnswers,\n maxLengthAnswers,\n maxLengthFirstColumnHeading,\n } = config;\n const rowsErrors = {};\n const columnsErrors = {};\n const errors = {};\n\n ['teacherInstructions', 'prompt', 'rationale'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n if (rows.length < minQuestions) {\n errors.noOfRowsError = `There should be at least ${minQuestions} question rows.`;\n } else if (rows.length > maxQuestions) {\n errors.noOfRowsError = `No more than ${maxQuestions} question rows should be defined.`;\n }\n\n (rows || []).forEach((row, index) => {\n const { id, values = [], title } = row;\n rowsErrors[id] = '';\n\n if (maxLengthQuestionsHeading && getInnerText(title).length > maxLengthQuestionsHeading) {\n rowsErrors[id] += `Content length should be maximum ${maxLengthQuestionsHeading} characters. `;\n }\n\n if (!getContent(title)) {\n rowsErrors[id] += 'Content should not be empty. ';\n } else {\n // check for identical content with the previous answers\n const identicalAnswer = rows.slice(0, index).some((r) => getContent(r.title) === getContent(title));\n\n if (identicalAnswer) {\n rowsErrors[id] += 'Content should be unique. ';\n }\n }\n\n const hasCorrectResponse = values.some((value) => !!value);\n\n if (!hasCorrectResponse) {\n rowsErrors[id] += 'No correct response defined.';\n }\n });\n\n if (maxAnswers && headers.length - 1 > maxAnswers) {\n errors.columnsLengthError = `There should be maximum ${maxAnswers} answers.`;\n }\n\n if (maxLengthFirstColumnHeading && headers[0].length > maxLengthFirstColumnHeading) {\n columnsErrors[0] = `Content length should be maximum ${maxLengthFirstColumnHeading} characters.`;\n }\n\n const headersContent = (headers || []).map((heading) => getContent(heading));\n headersContent.shift(); // remove first column since it does not require validation\n\n headersContent.forEach((heading, index) => {\n const headerIndex = index + 1; // we need to add 1 because we removed first header from validation\n columnsErrors[headerIndex] = '';\n\n if (maxLengthAnswers && getInnerText(heading).length > maxLengthAnswers) {\n columnsErrors[headerIndex] += `Content length should be maximum ${maxLengthAnswers} characters. `;\n }\n\n if (!heading) {\n columnsErrors[headerIndex] += 'Content should not be empty.';\n } else {\n // check for identical content with the previous headers\n const identicalAnswer = headersContent.slice(0, index).some((head) => head === heading);\n\n if (identicalAnswer) {\n columnsErrors[index + 1] += 'Content should be unique.';\n }\n }\n });\n\n const hasRowErrors = Object.values(rowsErrors).some((error) => (error || '').length);\n\n if (hasRowErrors) {\n errors.rowsErrors = rowsErrors;\n\n const noCorrectAnswer = Object.values(rowsErrors).some((error) =>\n (error || '').includes('No correct response defined.'),\n );\n\n if (noCorrectAnswer) {\n errors.correctResponseError =\n choiceMode === 'radio'\n ? 'There should be a correct response defined for every row.'\n : 'There should be at least one correct response defined for every row.';\n }\n }\n\n const hasColumnErrors = Object.values(columnsErrors).some((error) => (error || '').length);\n\n if (hasColumnErrors) {\n errors.columnsErrors = columnsErrors;\n }\n\n return errors;\n};\n"],"names":["choiceMode","feedbackEnabled","headers","layout","lockChoiceOrder","partialScoring","prompt","promptEnabled","rationale","rationaleEnabled","rows","scoringType","studentInstructionsEnabled","teacherInstructions","teacherInstructionsEnabled","toolbarEditorPosition","log","debug","getResponseCorrectness","model","answers","env","isPartialScoring","enabled","checkboxMode","Object","keys","length","totalCorrectAnswers","getTotalCorrectAnswers","getTotalCorrect","correctAnswers","incorrectAnswers","checkboxes","getCheckboxes","getCorrectRadios","getCorrectness","question","mode","forEach","row","answer","id","values","v","i","isEqual","matchingTable","noOfTotalCorrectAnswers","value","getPartialScore","totalCorrect","total","extraAnswers","score","parseFloat","toFixed","getOutComeScore","correctness","outcome","session","Promise","resolve","undefined","completed","isEmpty","empty","out","createDefaultModel","defaults","normalize","updateSession","normalizedQuestion","cloneDeep","correctResponse","correctInfo","lockChoices","getShuffledChoices","fb","getFeedbackForCorrectness","feedback","then","extraCSSRules","essentials","allowFeedback","shuffled","disabled","view","role","assign","createCorrectResponseSession","r","getInnerText","html","replaceAll","getContent","replace","validate","config","minQuestions","maxQuestions","maxLengthQuestionsHeading","maxAnswers","maxLengthAnswers","maxLengthFirstColumnHeading","rowsErrors","columnsErrors","errors","field","required","noOfRowsError","index","title","identicalAnswer","slice","some","hasCorrectResponse","columnsLengthError","headersContent","map","heading","shift","headerIndex","head","hasRowErrors","error","noCorrectAnswer","includes","correctResponseError","hasColumnErrors"],"mappings":"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"}
|