@pie-element/explicit-constructed-response 9.3.4-next.3 → 10.0.0-beta.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 +0 -11
- package/configure/CHANGELOG.md +0 -11
- package/configure/lib/alternateResponses.js +139 -184
- package/configure/lib/alternateResponses.js.map +1 -1
- package/configure/lib/alternateSection.js +279 -370
- package/configure/lib/alternateSection.js.map +1 -1
- package/configure/lib/defaults.js +2 -3
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/ecr-toolbar.js +127 -191
- package/configure/lib/ecr-toolbar.js.map +1 -1
- package/configure/lib/index.js +126 -203
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/main.js +436 -552
- package/configure/lib/main.js.map +1 -1
- package/configure/lib/markupUtils.js +26 -49
- package/configure/lib/markupUtils.js.map +1 -1
- package/configure/lib/utils.js +5 -5
- package/configure/lib/utils.js.map +1 -1
- package/configure/package.json +9 -7
- package/controller/CHANGELOG.md +0 -11
- package/controller/lib/defaults.js +2 -3
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +172 -260
- package/controller/lib/index.js.map +1 -1
- package/controller/package.json +3 -3
- package/lib/index.js +71 -115
- package/lib/index.js.map +1 -1
- package/lib/main.js +174 -248
- package/lib/main.js.map +1 -1
- package/lib/print.js +39 -83
- package/lib/print.js.map +1 -1
- package/package.json +14 -19
- package/esm/configure.js +0 -33096
- package/esm/configure.js.map +0 -1
- package/esm/controller.js +0 -5144
- package/esm/controller.js.map +0 -1
- package/esm/element.js +0 -11518
- package/esm/element.js.map +0 -1
- package/esm/package.json +0 -3
- package/esm/print.js +0 -12202
- package/esm/print.js.map +0 -1
- package/module/configure.js +0 -1
- package/module/controller.js +0 -7460
- package/module/demo.js +0 -45
- package/module/element.js +0 -1
- package/module/index.html +0 -21
- package/module/manifest.json +0 -22
- package/module/print-demo.js +0 -83
- package/module/print.html +0 -18
- package/module/print.js +0 -1
package/controller/lib/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
@@ -10,248 +9,184 @@ exports.model = model;
|
|
|
10
9
|
exports.normalize = void 0;
|
|
11
10
|
exports.outcome = outcome;
|
|
12
11
|
exports.validate = exports.prepareVal = exports.prepareChoice = void 0;
|
|
13
|
-
|
|
14
|
-
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
15
|
-
|
|
16
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
17
|
-
|
|
18
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
19
|
-
|
|
20
|
-
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
21
|
-
|
|
22
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
23
|
-
|
|
24
12
|
var _debug = _interopRequireDefault(require("debug"));
|
|
25
|
-
|
|
26
13
|
var _map = _interopRequireDefault(require("lodash/map"));
|
|
27
|
-
|
|
28
14
|
var _reduce = _interopRequireDefault(require("lodash/reduce"));
|
|
29
|
-
|
|
30
15
|
var _find = _interopRequireDefault(require("lodash/find"));
|
|
31
|
-
|
|
32
16
|
var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
|
|
33
|
-
|
|
34
17
|
var _he = require("he");
|
|
35
|
-
|
|
36
18
|
var _controllerUtils = require("@pie-lib/controller-utils");
|
|
37
|
-
|
|
38
19
|
var _translator = _interopRequireDefault(require("@pie-lib/translator"));
|
|
39
|
-
|
|
40
20
|
var _defaults = _interopRequireDefault(require("./defaults"));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
var prepareChoice = function prepareChoice(mode, defaultFeedback) {
|
|
50
|
-
return function (choice) {
|
|
51
|
-
var out = {
|
|
52
|
-
label: choice.label,
|
|
53
|
-
value: choice.value
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
if (mode === 'evaluate') {
|
|
57
|
-
out.correct = true;
|
|
58
|
-
var feedbackType = choice.feedback && choice.feedback.type || 'none';
|
|
59
|
-
|
|
60
|
-
if (feedbackType === 'default') {
|
|
61
|
-
out.feedback = defaultFeedback['correct'];
|
|
62
|
-
} else if (feedbackType === 'custom') {
|
|
63
|
-
out.feedback = choice.feedback.value;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return out;
|
|
21
|
+
const {
|
|
22
|
+
translator
|
|
23
|
+
} = _translator.default;
|
|
24
|
+
const log = (0, _debug.default)('explicit-constructed-response:controller');
|
|
25
|
+
const prepareChoice = (mode, defaultFeedback) => choice => {
|
|
26
|
+
const out = {
|
|
27
|
+
label: choice.label,
|
|
28
|
+
value: choice.value
|
|
68
29
|
};
|
|
30
|
+
if (mode === 'evaluate') {
|
|
31
|
+
out.correct = true;
|
|
32
|
+
const feedbackType = choice.feedback && choice.feedback.type || 'none';
|
|
33
|
+
if (feedbackType === 'default') {
|
|
34
|
+
out.feedback = defaultFeedback['correct'];
|
|
35
|
+
} else if (feedbackType === 'custom') {
|
|
36
|
+
out.feedback = choice.feedback.value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
69
40
|
};
|
|
70
|
-
|
|
71
41
|
exports.prepareChoice = prepareChoice;
|
|
72
|
-
|
|
73
|
-
var getFeedback = function getFeedback(value) {
|
|
42
|
+
const getFeedback = value => {
|
|
74
43
|
if (value) {
|
|
75
44
|
return 'correct';
|
|
76
45
|
}
|
|
77
|
-
|
|
78
46
|
return 'incorrect';
|
|
79
|
-
};
|
|
80
|
-
|
|
47
|
+
};
|
|
81
48
|
|
|
82
|
-
|
|
49
|
+
// also used in configure/src/markupUtils.js
|
|
50
|
+
const getAdjustedLength = length => {
|
|
51
|
+
if (Math.abs(length) === Infinity) {
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
83
54
|
if (length <= 2) {
|
|
84
55
|
return length + 2;
|
|
85
56
|
}
|
|
86
|
-
|
|
87
57
|
if (length <= 4) {
|
|
88
58
|
return length + 3;
|
|
89
59
|
}
|
|
90
|
-
|
|
91
60
|
if (length <= 6) {
|
|
92
61
|
return length + 4;
|
|
93
62
|
}
|
|
94
|
-
|
|
95
63
|
return length + 5;
|
|
96
|
-
};
|
|
97
|
-
|
|
64
|
+
};
|
|
98
65
|
|
|
99
|
-
|
|
66
|
+
// we can't use the dom parser here because it is not available in the node environment
|
|
67
|
+
const decodeHtmlEntities = str => {
|
|
100
68
|
if (!str) return '';
|
|
101
69
|
return str.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'|'/g, '\'').replace(/&/g, '&');
|
|
102
70
|
};
|
|
71
|
+
const normalize = question => ({
|
|
72
|
+
..._defaults.default,
|
|
73
|
+
...question
|
|
74
|
+
});
|
|
103
75
|
|
|
104
|
-
var normalize = function normalize(question) {
|
|
105
|
-
return _objectSpread(_objectSpread({}, _defaults["default"]), question);
|
|
106
|
-
};
|
|
107
76
|
/**
|
|
108
77
|
*
|
|
109
78
|
* @param {*} question
|
|
110
79
|
* @param {*} session
|
|
111
80
|
* @param {*} env
|
|
112
81
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
82
|
exports.normalize = normalize;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (question.choices) {
|
|
129
|
-
Object.keys(question.choices).forEach(function (key) {
|
|
130
|
-
question.choices[key] = (question.choices[key] || []).map(function (item, index) {
|
|
131
|
-
if (!item.value) {
|
|
132
|
-
log('Choice does not contain "value" property, which is required.', item);
|
|
133
|
-
return _objectSpread({
|
|
134
|
-
value: "".concat(index)
|
|
135
|
-
}, item);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return item;
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
normalizedQuestion = normalize(question);
|
|
144
|
-
defaultFeedback = Object.assign({
|
|
145
|
-
correct: 'Correct',
|
|
146
|
-
incorrect: 'Incorrect'
|
|
147
|
-
}, normalizedQuestion.defaultFeedback);
|
|
148
|
-
prepareChoiceFn = prepareChoice(env.mode, defaultFeedback);
|
|
149
|
-
choices = (0, _reduce["default"])(normalizedQuestion.choices, function (obj, area, key) {
|
|
150
|
-
obj[key] = (0, _map["default"])(area, prepareChoiceFn);
|
|
151
|
-
return obj;
|
|
152
|
-
}, {});
|
|
153
|
-
_ref2 = session || {}, _ref2$value = _ref2.value, value = _ref2$value === void 0 ? {} : _ref2$value;
|
|
154
|
-
feedback = env.mode === 'evaluate' ? (0, _reduce["default"])(normalizedQuestion.choices, function (obj, respArea, key) {
|
|
155
|
-
var chosenValue = value && value[key];
|
|
156
|
-
var val = !(0, _isEmpty["default"])(chosenValue) && (0, _find["default"])(respArea, function (c) {
|
|
157
|
-
return prepareVal(c.label) === prepareVal(chosenValue);
|
|
158
|
-
});
|
|
159
|
-
obj[key] = getFeedback(val);
|
|
160
|
-
return obj;
|
|
161
|
-
}, {}) : {}; // check if at least one choice has an alternate
|
|
162
|
-
|
|
163
|
-
showNote = Object.values(choices).some(function (choice) {
|
|
164
|
-
return (choice === null || choice === void 0 ? void 0 : choice.length) > 1;
|
|
165
|
-
});
|
|
166
|
-
note = normalizedQuestion.note || translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
167
|
-
lng: normalizedQuestion.language
|
|
168
|
-
});
|
|
169
|
-
_normalizedQuestion$m = normalizedQuestion.maxLengthPerChoice, maxLengthPerChoice = _normalizedQuestion$m === void 0 ? [] : _normalizedQuestion$m, maxLengthPerChoiceEnabled = normalizedQuestion.maxLengthPerChoiceEnabled;
|
|
170
|
-
undefinedLengths = !maxLengthPerChoice.length; // calculate maxLengthPerChoice array if it is not defined or defined incorrectly
|
|
171
|
-
|
|
172
|
-
Object.values(choices).forEach(function (choice, index) {
|
|
173
|
-
var labelLengthsArr = (choice || []).map(function (choice) {
|
|
174
|
-
return decodeHtmlEntities(choice.label || '').length;
|
|
175
|
-
});
|
|
176
|
-
var length = Math.max.apply(Math, (0, _toConsumableArray2["default"])(labelLengthsArr));
|
|
177
|
-
|
|
178
|
-
if (undefinedLengths || !maxLengthPerChoice[index] || maxLengthPerChoice[index] < length || maxLengthPerChoice[index] > length + 10) {
|
|
179
|
-
maxLengthPerChoice[index] = getAdjustedLength(length);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
out = {
|
|
183
|
-
choices: choices,
|
|
184
|
-
disabled: env.mode !== 'gather',
|
|
185
|
-
displayType: normalizedQuestion.displayType,
|
|
186
|
-
mode: env.mode,
|
|
187
|
-
role: env.role,
|
|
188
|
-
feedback: feedback,
|
|
189
|
-
language: normalizedQuestion.language,
|
|
190
|
-
markup: normalizedQuestion.markup,
|
|
191
|
-
maxLengthPerChoice: maxLengthPerChoice,
|
|
192
|
-
maxLengthPerChoiceEnabled: maxLengthPerChoiceEnabled,
|
|
193
|
-
note: note,
|
|
194
|
-
playerSpellCheckEnabled: normalizedQuestion.playerSpellCheckEnabled,
|
|
195
|
-
prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : _defaults["default"].prompt,
|
|
196
|
-
rationale: _defaults["default"].rationale,
|
|
197
|
-
responseCorrect: env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined,
|
|
198
|
-
showNote: showNote,
|
|
199
|
-
teacherInstructions: _defaults["default"].teacherInstructions,
|
|
200
|
-
responseAreaInputConfiguration: normalizedQuestion.responseAreaInputConfiguration,
|
|
201
|
-
extraCSSRules: normalizedQuestion.extraCSSRules
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
205
|
-
out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : _defaults["default"].rationale;
|
|
206
|
-
out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : _defaults["default"].teacherInstructions;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
resolve(out);
|
|
210
|
-
|
|
211
|
-
case 15:
|
|
212
|
-
case "end":
|
|
213
|
-
return _context.stop();
|
|
214
|
-
}
|
|
83
|
+
async function model(question, session, env) {
|
|
84
|
+
// this was added to treat an exception, when the model has choices without
|
|
85
|
+
// the "value" property like: { label: 'test' }
|
|
86
|
+
if (question.choices) {
|
|
87
|
+
Object.keys(question.choices).forEach(key => {
|
|
88
|
+
question.choices[key] = (question.choices[key] || []).map((item, index) => {
|
|
89
|
+
if (!item.value) {
|
|
90
|
+
log('Choice does not contain "value" property, which is required.', item);
|
|
91
|
+
return {
|
|
92
|
+
value: `${index}`,
|
|
93
|
+
...item
|
|
94
|
+
};
|
|
215
95
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
96
|
+
return item;
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const normalizedQuestion = normalize(question);
|
|
101
|
+
const defaultFeedback = Object.assign({
|
|
102
|
+
correct: 'Correct',
|
|
103
|
+
incorrect: 'Incorrect'
|
|
104
|
+
}, normalizedQuestion.defaultFeedback);
|
|
105
|
+
const prepareChoiceFn = prepareChoice(env.mode, defaultFeedback);
|
|
106
|
+
const choices = (0, _reduce.default)(normalizedQuestion.choices, (obj, area, key) => {
|
|
107
|
+
obj[key] = (0, _map.default)(area, prepareChoiceFn);
|
|
108
|
+
return obj;
|
|
109
|
+
}, {});
|
|
110
|
+
const {
|
|
111
|
+
value = {}
|
|
112
|
+
} = session || {};
|
|
113
|
+
const feedback = env.mode === 'evaluate' ? (0, _reduce.default)(normalizedQuestion.choices, (obj, respArea, key) => {
|
|
114
|
+
const chosenValue = value && value[key];
|
|
115
|
+
const val = !(0, _isEmpty.default)(chosenValue) && (0, _find.default)(respArea, c => prepareVal(c.label) === prepareVal(chosenValue));
|
|
116
|
+
obj[key] = getFeedback(val);
|
|
117
|
+
return obj;
|
|
118
|
+
}, {}) : {};
|
|
119
|
+
|
|
120
|
+
// check if at least one choice has an alternate
|
|
121
|
+
const showNote = Object.values(choices).some(choice => choice?.length > 1);
|
|
122
|
+
const note = normalizedQuestion.note || translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
123
|
+
lng: normalizedQuestion.language
|
|
124
|
+
});
|
|
125
|
+
const {
|
|
126
|
+
maxLengthPerChoice = [],
|
|
127
|
+
maxLengthPerChoiceEnabled
|
|
128
|
+
} = normalizedQuestion;
|
|
129
|
+
const undefinedLengths = !maxLengthPerChoice.length;
|
|
130
|
+
|
|
131
|
+
// calculate maxLengthPerChoice array if it is not defined or defined incorrectly
|
|
132
|
+
Object.values(choices).forEach((choice, index) => {
|
|
133
|
+
const labelLengthsArr = (choice || []).map(choice => decodeHtmlEntities(choice.label || '').length);
|
|
134
|
+
const length = Math.max(...labelLengthsArr);
|
|
135
|
+
if (undefinedLengths || !maxLengthPerChoice[index] || maxLengthPerChoice[index] < length || maxLengthPerChoice[index] > length + 10) {
|
|
136
|
+
maxLengthPerChoice[index] = getAdjustedLength(length);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
const out = {
|
|
140
|
+
choices,
|
|
141
|
+
disabled: env.mode !== 'gather',
|
|
142
|
+
displayType: normalizedQuestion.displayType,
|
|
143
|
+
mode: env.mode,
|
|
144
|
+
role: env.role,
|
|
145
|
+
feedback,
|
|
146
|
+
language: normalizedQuestion.language,
|
|
147
|
+
markup: normalizedQuestion.markup,
|
|
148
|
+
maxLengthPerChoice,
|
|
149
|
+
maxLengthPerChoiceEnabled,
|
|
150
|
+
note,
|
|
151
|
+
playerSpellCheckEnabled: normalizedQuestion.playerSpellCheckEnabled,
|
|
152
|
+
prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : _defaults.default.prompt,
|
|
153
|
+
rationale: _defaults.default.rationale,
|
|
154
|
+
responseCorrect: env.mode === 'evaluate' ? getScore(normalizedQuestion, session) === 1 : undefined,
|
|
155
|
+
showNote,
|
|
156
|
+
teacherInstructions: _defaults.default.teacherInstructions,
|
|
157
|
+
responseAreaInputConfiguration: normalizedQuestion.responseAreaInputConfiguration,
|
|
158
|
+
extraCSSRules: normalizedQuestion.extraCSSRules
|
|
159
|
+
};
|
|
160
|
+
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
161
|
+
out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : _defaults.default.rationale;
|
|
162
|
+
out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : _defaults.default.teacherInstructions;
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
223
165
|
}
|
|
224
|
-
|
|
225
|
-
var prepareVal = function prepareVal(html) {
|
|
166
|
+
const prepareVal = html => {
|
|
226
167
|
return decodeHTML(getInnerText(html).trim());
|
|
227
168
|
};
|
|
228
|
-
|
|
229
169
|
exports.prepareVal = prepareVal;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (!session || (0, _isEmpty["default"])(session) || !value) {
|
|
170
|
+
const getScore = (config, session) => {
|
|
171
|
+
const {
|
|
172
|
+
value
|
|
173
|
+
} = session || {};
|
|
174
|
+
if (!session || (0, _isEmpty.default)(session) || !value) {
|
|
236
175
|
return 0;
|
|
237
176
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if ((0, _isEmpty["default"])(chosenValue) || !(0, _find["default"])(respArea, function (c) {
|
|
245
|
-
return prepareVal(c.label) === prepareVal(chosenValue);
|
|
246
|
-
})) {
|
|
177
|
+
const responseAreas = config.markup && config.markup.match(/\{\{(.+?)\}\}/g);
|
|
178
|
+
const maxScore = responseAreas ? responseAreas.length : 0;
|
|
179
|
+
const correctCount = (0, _reduce.default)(config.choices, (total, respArea, key) => {
|
|
180
|
+
const chosenValue = value && value[key];
|
|
181
|
+
if ((0, _isEmpty.default)(chosenValue) || !(0, _find.default)(respArea, c => prepareVal(c.label) === prepareVal(chosenValue))) {
|
|
247
182
|
return total;
|
|
248
183
|
}
|
|
249
|
-
|
|
250
184
|
return total + 1;
|
|
251
185
|
}, 0);
|
|
252
|
-
|
|
186
|
+
const str = maxScore ? (correctCount / maxScore).toFixed(2) : 0;
|
|
253
187
|
return parseFloat(str);
|
|
254
188
|
};
|
|
189
|
+
|
|
255
190
|
/**
|
|
256
191
|
* The score is partial by default for checkbox mode, allOrNothing for radio mode.
|
|
257
192
|
* To disable partial scoring for checkbox mode you either set model.partialScoring = false or env.partialScoring =
|
|
@@ -263,50 +198,44 @@ var getScore = function getScore(config, session) {
|
|
|
263
198
|
* @param {boolean} env.partialScoring - is partial scoring enabled (if undefined default to true) This overrides
|
|
264
199
|
* `model.partialScoring`.
|
|
265
200
|
*/
|
|
266
|
-
|
|
267
|
-
|
|
268
201
|
exports.getScore = getScore;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
var partialScoringEnabled = _controllerUtils.partialScoring.enabled(model, env);
|
|
274
|
-
|
|
275
|
-
var score = getScore(model, session);
|
|
202
|
+
function outcome(model, session, env = {}) {
|
|
203
|
+
return new Promise(resolve => {
|
|
204
|
+
const partialScoringEnabled = _controllerUtils.partialScoring.enabled(model, env);
|
|
205
|
+
const score = getScore(model, session);
|
|
276
206
|
resolve({
|
|
277
207
|
score: partialScoringEnabled ? score : score === 1 ? 1 : 0,
|
|
278
|
-
empty: (0, _isEmpty
|
|
208
|
+
empty: (0, _isEmpty.default)(session)
|
|
279
209
|
});
|
|
280
210
|
});
|
|
281
211
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return new Promise(function (resolve) {
|
|
212
|
+
const createCorrectResponseSession = (question, env) => {
|
|
213
|
+
return new Promise(resolve => {
|
|
285
214
|
if (env.mode !== 'evaluate' && env.role === 'instructor') {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
215
|
+
const {
|
|
216
|
+
choices
|
|
217
|
+
} = question;
|
|
218
|
+
const value = {};
|
|
219
|
+
Object.keys(choices).forEach((key, i) => {
|
|
289
220
|
value[i] = choices[key][0].label;
|
|
290
221
|
});
|
|
291
222
|
resolve({
|
|
292
223
|
id: '1',
|
|
293
|
-
value
|
|
224
|
+
value
|
|
294
225
|
});
|
|
295
226
|
} else {
|
|
296
227
|
resolve(null);
|
|
297
228
|
}
|
|
298
229
|
});
|
|
299
|
-
};
|
|
300
|
-
// const getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');
|
|
301
|
-
|
|
230
|
+
};
|
|
302
231
|
|
|
232
|
+
// remove all html tags
|
|
233
|
+
// const getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');
|
|
303
234
|
exports.createCorrectResponseSession = createCorrectResponseSession;
|
|
304
|
-
|
|
305
|
-
var getInnerText = function getInnerText(html) {
|
|
235
|
+
const getInnerText = html => {
|
|
306
236
|
if (typeof html !== 'string') {
|
|
307
237
|
return '';
|
|
308
238
|
}
|
|
309
|
-
|
|
310
239
|
if (typeof html.replaceAll === 'function') {
|
|
311
240
|
return html.replaceAll(/<[^>]*>/g, '');
|
|
312
241
|
} else {
|
|
@@ -314,73 +243,56 @@ var getInnerText = function getInnerText(html) {
|
|
|
314
243
|
return html.replace(/<[^>]*>/g, '');
|
|
315
244
|
}
|
|
316
245
|
};
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
var allChoicesErrors = {};
|
|
334
|
-
var errors = {};
|
|
335
|
-
['teacherInstructions', 'prompt', 'rationale'].forEach(function (field) {
|
|
336
|
-
var _config$field;
|
|
337
|
-
|
|
338
|
-
if ((_config$field = config[field]) !== null && _config$field !== void 0 && _config$field.required && !getContent(model[field])) {
|
|
246
|
+
const decodeHTML = html => (0, _he.decode)(html);
|
|
247
|
+
|
|
248
|
+
// remove all html tags except img, iframe and source tag for audio
|
|
249
|
+
const getContent = html => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
|
|
250
|
+
const validate = (model = {}, config = {}) => {
|
|
251
|
+
const {
|
|
252
|
+
choices,
|
|
253
|
+
markup
|
|
254
|
+
} = model;
|
|
255
|
+
const {
|
|
256
|
+
maxResponseAreas
|
|
257
|
+
} = config;
|
|
258
|
+
const allChoicesErrors = {};
|
|
259
|
+
const errors = {};
|
|
260
|
+
['teacherInstructions', 'prompt', 'rationale'].forEach(field => {
|
|
261
|
+
if (config[field]?.required && !getContent(model[field])) {
|
|
339
262
|
errors[field] = 'This field is required.';
|
|
340
263
|
}
|
|
341
264
|
});
|
|
342
|
-
Object.entries(choices || {}).forEach(
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
var value = choice.value,
|
|
351
|
-
label = choice.label;
|
|
352
|
-
|
|
265
|
+
Object.entries(choices || {}).forEach(([key, values]) => {
|
|
266
|
+
const reversedChoices = [...(values || [])].reverse();
|
|
267
|
+
const choicesErrors = {};
|
|
268
|
+
reversedChoices.forEach((choice, index) => {
|
|
269
|
+
const {
|
|
270
|
+
value,
|
|
271
|
+
label
|
|
272
|
+
} = choice;
|
|
353
273
|
if (label === '' || label === '<div></div>') {
|
|
354
274
|
choicesErrors[value] = 'Content should not be empty.';
|
|
355
275
|
} else {
|
|
356
|
-
|
|
357
|
-
return c.label === label;
|
|
358
|
-
});
|
|
359
|
-
|
|
276
|
+
const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.label === label);
|
|
360
277
|
if (identicalAnswer) {
|
|
361
278
|
choicesErrors[value] = 'Content should be unique.';
|
|
362
279
|
}
|
|
363
280
|
}
|
|
364
281
|
});
|
|
365
|
-
|
|
366
|
-
if (!(0, _isEmpty["default"])(choicesErrors)) {
|
|
282
|
+
if (!(0, _isEmpty.default)(choicesErrors)) {
|
|
367
283
|
allChoicesErrors[key] = choicesErrors;
|
|
368
284
|
}
|
|
369
285
|
});
|
|
370
|
-
|
|
371
|
-
|
|
286
|
+
const nbOfResponseAreas = (markup.match(/\{\{(\d+)\}\}/g) || []).length;
|
|
372
287
|
if (nbOfResponseAreas > maxResponseAreas) {
|
|
373
|
-
errors.responseAreas =
|
|
288
|
+
errors.responseAreas = `No more than ${maxResponseAreas} response areas should be defined.`;
|
|
374
289
|
} else if (nbOfResponseAreas < 1) {
|
|
375
290
|
errors.responseAreas = 'There should be at least 1 response area defined.';
|
|
376
291
|
}
|
|
377
|
-
|
|
378
|
-
if (!(0, _isEmpty["default"])(allChoicesErrors)) {
|
|
292
|
+
if (!(0, _isEmpty.default)(allChoicesErrors)) {
|
|
379
293
|
errors.choices = allChoicesErrors;
|
|
380
294
|
}
|
|
381
|
-
|
|
382
295
|
return errors;
|
|
383
296
|
};
|
|
384
|
-
|
|
385
297
|
exports.validate = validate;
|
|
386
298
|
//# sourceMappingURL=index.js.map
|