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