@pie-element/categorize 11.0.5-esm.1 → 11.2.0-mui-update.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/CHANGELOG.md +81 -0
- package/configure/CHANGELOG.md +74 -0
- package/configure/lib/defaults.js +2 -5
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/design/builder.js +15 -33
- package/configure/lib/design/builder.js.map +1 -1
- package/configure/lib/design/buttons.js +44 -95
- package/configure/lib/design/buttons.js.map +1 -1
- package/configure/lib/design/categories/RowLabel.js +32 -45
- package/configure/lib/design/categories/RowLabel.js.map +1 -1
- package/configure/lib/design/categories/alternateResponses.js +102 -251
- package/configure/lib/design/categories/alternateResponses.js.map +1 -1
- package/configure/lib/design/categories/category.js +138 -208
- package/configure/lib/design/categories/category.js.map +1 -1
- package/configure/lib/design/categories/choice-preview.js +59 -126
- package/configure/lib/design/categories/choice-preview.js.map +1 -1
- package/configure/lib/design/categories/droppable-placeholder.js +76 -165
- package/configure/lib/design/categories/droppable-placeholder.js.map +1 -1
- package/configure/lib/design/categories/index.js +199 -384
- package/configure/lib/design/categories/index.js.map +1 -1
- package/configure/lib/design/choices/choice.js +160 -263
- package/configure/lib/design/choices/choice.js.map +1 -1
- package/configure/lib/design/choices/config.js +46 -98
- package/configure/lib/design/choices/config.js.map +1 -1
- package/configure/lib/design/choices/index.js +152 -236
- package/configure/lib/design/choices/index.js.map +1 -1
- package/configure/lib/design/header.js +62 -111
- package/configure/lib/design/header.js.map +1 -1
- package/configure/lib/design/index.js +632 -476
- package/configure/lib/design/index.js.map +1 -1
- package/configure/lib/design/input-header.js +97 -149
- package/configure/lib/design/input-header.js.map +1 -1
- package/configure/lib/design/utils.js +4 -15
- package/configure/lib/design/utils.js.map +1 -1
- package/configure/lib/index.js +120 -183
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/main.js +31 -74
- package/configure/lib/main.js.map +1 -1
- package/configure/lib/utils.js +22 -32
- package/configure/lib/utils.js.map +1 -1
- package/configure/package.json +15 -14
- package/controller/CHANGELOG.md +62 -0
- package/controller/lib/defaults.js +2 -5
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +238 -315
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js +40 -31
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +5 -5
- package/lib/categorize/categories.js +110 -164
- package/lib/categorize/categories.js.map +1 -1
- package/lib/categorize/category.js +72 -122
- package/lib/categorize/category.js.map +1 -1
- package/lib/categorize/choice.js +116 -245
- package/lib/categorize/choice.js.map +1 -1
- package/lib/categorize/choices.js +66 -131
- package/lib/categorize/choices.js.map +1 -1
- package/lib/categorize/droppable-placeholder.js +49 -103
- package/lib/categorize/droppable-placeholder.js.map +1 -1
- package/lib/categorize/grid-content.js +39 -87
- package/lib/categorize/grid-content.js.map +1 -1
- package/lib/categorize/index.js +341 -316
- package/lib/categorize/index.js.map +1 -1
- package/lib/index.js +286 -271
- package/lib/index.js.map +1 -1
- package/package.json +17 -31
- package/LICENSE.md +0 -5
- package/esm/configure.js +0 -5025
- package/esm/configure.js.map +0 -1
- package/esm/controller.js +0 -456
- package/esm/controller.js.map +0 -1
- package/esm/element.js +0 -3118
- package/esm/element.js.map +0 -1
- package/module/configure.js +0 -1
- package/module/controller.js +0 -6076
- package/module/demo.js +0 -382
- package/module/element.js +0 -1
- package/module/index.html +0 -21
- package/module/manifest.json +0 -22
- package/module/print-demo.js +0 -420
- package/module/print.html +0 -18
package/controller/lib/index.js
CHANGED
|
@@ -1,144 +1,110 @@
|
|
|
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
|
});
|
|
8
7
|
exports.outcome = exports.normalize = exports.model = exports.getTotalScore = exports.getPartialScore = exports.getCorrectness = exports.createDefaultModel = exports.createCorrectResponseSession = void 0;
|
|
9
8
|
Object.defineProperty(exports, "score", {
|
|
10
9
|
enumerable: true,
|
|
11
|
-
get: function
|
|
10
|
+
get: function () {
|
|
12
11
|
return _categorize.score;
|
|
13
12
|
}
|
|
14
13
|
});
|
|
15
14
|
exports.validate = void 0;
|
|
16
|
-
|
|
17
|
-
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
18
|
-
|
|
19
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
20
|
-
|
|
21
|
-
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
22
|
-
|
|
23
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
24
|
-
|
|
25
15
|
var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
|
|
26
|
-
|
|
27
16
|
var _categorize = require("@pie-lib/categorize");
|
|
28
|
-
|
|
29
17
|
var _feedback = require("@pie-lib/feedback");
|
|
30
|
-
|
|
31
18
|
var _controllerUtils = require("@pie-lib/controller-utils");
|
|
32
|
-
|
|
33
19
|
var _translator = _interopRequireDefault(require("@pie-lib/translator"));
|
|
34
|
-
|
|
35
20
|
var _defaults = _interopRequireDefault(require("./defaults"));
|
|
36
|
-
|
|
37
21
|
var _utils = require("./utils");
|
|
22
|
+
const {
|
|
23
|
+
translator
|
|
24
|
+
} = _translator.default;
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
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; }
|
|
42
|
-
|
|
43
|
-
var translator = _translator["default"].translator;
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
44
27
|
|
|
45
|
-
|
|
28
|
+
const getPartialScore = (correctResponse, builtCategories) => {
|
|
46
29
|
// in the resulted best scenario we make a sum with all the correct responses
|
|
47
30
|
// and all the placements
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}, {
|
|
31
|
+
const {
|
|
32
|
+
placements,
|
|
33
|
+
score
|
|
34
|
+
} = builtCategories.reduce((acc, {
|
|
35
|
+
choices = []
|
|
36
|
+
}) => ({
|
|
37
|
+
placements: acc.placements + choices.length,
|
|
38
|
+
score: acc.score + choices.filter(ch => ch.correct).length
|
|
39
|
+
}), {
|
|
58
40
|
placements: 0,
|
|
59
41
|
score: 0
|
|
60
|
-
})
|
|
61
|
-
placements = _builtCategories$redu.placements,
|
|
62
|
-
score = _builtCategories$redu.score; // in the correct response, we make a sum of the max possible score
|
|
63
|
-
|
|
42
|
+
});
|
|
64
43
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
44
|
+
// in the correct response, we make a sum of the max possible score
|
|
45
|
+
const {
|
|
46
|
+
maxScore
|
|
47
|
+
} = correctResponse.reduce((acc, {
|
|
48
|
+
choices
|
|
49
|
+
}) => ({
|
|
50
|
+
maxScore: acc.maxScore + choices.length
|
|
51
|
+
}), {
|
|
71
52
|
maxScore: 0
|
|
72
|
-
})
|
|
73
|
-
maxScore = _correctResponse$redu.maxScore; // if there are any extra placements, we subtract from the obtained score
|
|
74
|
-
|
|
53
|
+
});
|
|
75
54
|
|
|
76
|
-
|
|
77
|
-
|
|
55
|
+
// if there are any extra placements, we subtract from the obtained score
|
|
56
|
+
const extraPlacements = placements > maxScore ? placements - maxScore : 0;
|
|
57
|
+
const totalScore = (score - extraPlacements) / maxScore;
|
|
78
58
|
return totalScore < 0 ? 0 : parseFloat(totalScore.toFixed(2));
|
|
79
59
|
};
|
|
80
|
-
|
|
81
60
|
exports.getPartialScore = getPartialScore;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return correctResponse.map(function (c) {
|
|
85
|
-
return c.alternateResponses;
|
|
86
|
-
}).filter(function (alternate) {
|
|
87
|
-
return alternate;
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
var getTotalScore = function getTotalScore(question, session, env) {
|
|
61
|
+
const getAlternates = correctResponse => correctResponse.map(c => c.alternateResponses).filter(alternate => alternate);
|
|
62
|
+
const getTotalScore = (question, session, env) => {
|
|
92
63
|
if (!session) {
|
|
93
64
|
return 0;
|
|
94
65
|
}
|
|
95
|
-
|
|
96
66
|
if (Object.keys(session).length === 0) {
|
|
97
67
|
return 0;
|
|
98
68
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
69
|
+
const {
|
|
70
|
+
categories,
|
|
71
|
+
choices
|
|
72
|
+
} = question || {};
|
|
73
|
+
let {
|
|
74
|
+
correctResponse
|
|
75
|
+
} = question || {};
|
|
76
|
+
let {
|
|
77
|
+
answers
|
|
78
|
+
} = session || {};
|
|
110
79
|
answers = answers || [];
|
|
111
|
-
correctResponse = correctResponse || [];
|
|
112
|
-
// so we get the best scenario and calculate the score
|
|
113
|
-
|
|
114
|
-
var _buildState = (0, _categorize.buildState)(categories, choices, answers, correctResponse),
|
|
115
|
-
builtCategories = _buildState.categories,
|
|
116
|
-
correct = _buildState.correct;
|
|
117
|
-
|
|
118
|
-
var alternates = getAlternates(correctResponse);
|
|
119
|
-
|
|
120
|
-
var enabled = _controllerUtils.partialScoring.enabled(question, env); // if there are any alternates, there will be no partial scoring!
|
|
121
|
-
|
|
80
|
+
correctResponse = correctResponse || [];
|
|
122
81
|
|
|
82
|
+
// this function is used in pie-ui/categorize as well, in order to get the best scenario
|
|
83
|
+
// so we get the best scenario and calculate the score
|
|
84
|
+
const {
|
|
85
|
+
categories: builtCategories,
|
|
86
|
+
correct
|
|
87
|
+
} = (0, _categorize.buildState)(categories, choices, answers, correctResponse);
|
|
88
|
+
const alternates = getAlternates(correctResponse);
|
|
89
|
+
const enabled = _controllerUtils.partialScoring.enabled(question, env);
|
|
90
|
+
|
|
91
|
+
// if there are any alternates, there will be no partial scoring!
|
|
123
92
|
if (enabled && !alternates.length) {
|
|
124
93
|
// we apply partial scoring
|
|
125
94
|
return getPartialScore(correctResponse, builtCategories);
|
|
126
|
-
}
|
|
127
|
-
|
|
95
|
+
}
|
|
128
96
|
|
|
97
|
+
// else we apply dichotomous
|
|
129
98
|
return correct ? 1 : 0;
|
|
130
99
|
};
|
|
131
|
-
|
|
132
100
|
exports.getTotalScore = getTotalScore;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return new Promise(function (resolve) {
|
|
101
|
+
const getCorrectness = (question, session, env) => {
|
|
102
|
+
return new Promise(resolve => {
|
|
136
103
|
if (env.mode === 'evaluate') {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (_score === 1) {
|
|
104
|
+
const score = getTotalScore(question, session, env);
|
|
105
|
+
if (score === 1) {
|
|
140
106
|
resolve('correct');
|
|
141
|
-
} else if (
|
|
107
|
+
} else if (score === 0) {
|
|
142
108
|
resolve('incorrect');
|
|
143
109
|
} else {
|
|
144
110
|
resolve('partially-correct');
|
|
@@ -148,21 +114,19 @@ var getCorrectness = function getCorrectness(question, session, env) {
|
|
|
148
114
|
}
|
|
149
115
|
});
|
|
150
116
|
};
|
|
151
|
-
|
|
152
117
|
exports.getCorrectness = getCorrectness;
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
resolve(_objectSpread(_objectSpread({}, _defaults["default"]), model));
|
|
118
|
+
const createDefaultModel = (model = {}) => new Promise(resolve => {
|
|
119
|
+
resolve({
|
|
120
|
+
..._defaults.default,
|
|
121
|
+
...model
|
|
158
122
|
});
|
|
159
|
-
};
|
|
160
|
-
|
|
123
|
+
});
|
|
161
124
|
exports.createDefaultModel = createDefaultModel;
|
|
125
|
+
const normalize = question => ({
|
|
126
|
+
..._defaults.default,
|
|
127
|
+
...question
|
|
128
|
+
});
|
|
162
129
|
|
|
163
|
-
var normalize = function normalize(question) {
|
|
164
|
-
return _objectSpread(_objectSpread({}, _defaults["default"]), question);
|
|
165
|
-
};
|
|
166
130
|
/**
|
|
167
131
|
*
|
|
168
132
|
* @param {*} question
|
|
@@ -170,144 +134,129 @@ var normalize = function normalize(question) {
|
|
|
170
134
|
* @param {*} env
|
|
171
135
|
* @param {*} updateSession - optional - a function that will set the properties passed into it on the session.
|
|
172
136
|
*/
|
|
173
|
-
|
|
174
|
-
|
|
175
137
|
exports.normalize = normalize;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
_context.next = 17;
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
_context.next = 16;
|
|
223
|
-
return (0, _controllerUtils.getShuffledChoices)(choices, session, updateSession, 'id');
|
|
224
|
-
|
|
225
|
-
case 16:
|
|
226
|
-
choices = _context.sent;
|
|
227
|
-
|
|
228
|
-
case 17:
|
|
229
|
-
if (!note) {
|
|
230
|
-
note = translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
231
|
-
lng: language
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
alternates = getAlternates(filteredCorrectResponse);
|
|
236
|
-
out = {
|
|
237
|
-
categories: categories || [],
|
|
238
|
-
categoriesPerRow: categoriesPerRow || 2,
|
|
239
|
-
maxChoicesPerCategory: maxChoicesPerCategory,
|
|
240
|
-
correctness: answerCorrectness,
|
|
241
|
-
choices: choices || [],
|
|
242
|
-
choicesLabel: choicesLabel || '',
|
|
243
|
-
choicesPosition: choicesPosition,
|
|
244
|
-
disabled: mode !== 'gather',
|
|
245
|
-
feedback: fb,
|
|
246
|
-
lockChoiceOrder: lockChoiceOrder,
|
|
247
|
-
prompt: promptEnabled ? prompt : null,
|
|
248
|
-
rowLabels: rowLabels,
|
|
249
|
-
note: note,
|
|
250
|
-
env: env,
|
|
251
|
-
showNote: alternates && alternates.length > 0,
|
|
252
|
-
correctResponse: mode === 'evaluate' ? filteredCorrectResponse : undefined,
|
|
253
|
-
language: language,
|
|
254
|
-
extraCSSRules: extraCSSRules,
|
|
255
|
-
fontSizeFactor: fontSizeFactor,
|
|
256
|
-
minRowHeight: minRowHeight,
|
|
257
|
-
autoplayAudioEnabled: autoplayAudioEnabled,
|
|
258
|
-
completeAudioEnabled: completeAudioEnabled,
|
|
259
|
-
customAudioButton: customAudioButton
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {
|
|
263
|
-
out.rationale = rationaleEnabled ? rationale : null;
|
|
264
|
-
out.teacherInstructions = teacherInstructionsEnabled ? teacherInstructions : null;
|
|
265
|
-
} else {
|
|
266
|
-
out.rationale = null;
|
|
267
|
-
out.teacherInstructions = null;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
resolve(out);
|
|
271
|
-
|
|
272
|
-
case 22:
|
|
273
|
-
case "end":
|
|
274
|
-
return _context.stop();
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}, _callee);
|
|
278
|
-
}));
|
|
279
|
-
|
|
280
|
-
return function (_x) {
|
|
281
|
-
return _ref6.apply(this, arguments);
|
|
138
|
+
const model = (question, session, env, updateSession) => new Promise(async resolve => {
|
|
139
|
+
const normalizedQuestion = normalize(question);
|
|
140
|
+
const answerCorrectness = await getCorrectness(normalizedQuestion, session, env);
|
|
141
|
+
const {
|
|
142
|
+
mode,
|
|
143
|
+
role
|
|
144
|
+
} = env || {};
|
|
145
|
+
const {
|
|
146
|
+
categories,
|
|
147
|
+
categoriesPerRow,
|
|
148
|
+
choicesLabel,
|
|
149
|
+
choicesPosition,
|
|
150
|
+
correctResponse,
|
|
151
|
+
feedback,
|
|
152
|
+
feedbackEnabled,
|
|
153
|
+
promptEnabled,
|
|
154
|
+
prompt,
|
|
155
|
+
rowLabels,
|
|
156
|
+
rationaleEnabled,
|
|
157
|
+
rationale,
|
|
158
|
+
teacherInstructionsEnabled,
|
|
159
|
+
teacherInstructions,
|
|
160
|
+
language,
|
|
161
|
+
maxChoicesPerCategory,
|
|
162
|
+
extraCSSRules,
|
|
163
|
+
minRowHeight,
|
|
164
|
+
fontSizeFactor,
|
|
165
|
+
autoplayAudioEnabled,
|
|
166
|
+
completeAudioEnabled,
|
|
167
|
+
customAudioButton
|
|
168
|
+
} = normalizedQuestion;
|
|
169
|
+
let {
|
|
170
|
+
choices,
|
|
171
|
+
note
|
|
172
|
+
} = normalizedQuestion;
|
|
173
|
+
let fb;
|
|
174
|
+
const lockChoiceOrder = (0, _controllerUtils.lockChoices)(normalizedQuestion, session, env);
|
|
175
|
+
const filteredCorrectResponse = correctResponse.map(response => {
|
|
176
|
+
const filteredChoices = (response.choices || []).filter(choice => choice !== 'null');
|
|
177
|
+
return {
|
|
178
|
+
...response,
|
|
179
|
+
choices: filteredChoices
|
|
282
180
|
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
181
|
+
});
|
|
182
|
+
if (mode === 'evaluate' && feedbackEnabled) {
|
|
183
|
+
fb = await (0, _feedback.getFeedbackForCorrectness)(answerCorrectness, feedback);
|
|
184
|
+
}
|
|
185
|
+
if (!lockChoiceOrder) {
|
|
186
|
+
choices = await (0, _controllerUtils.getShuffledChoices)(choices, session, updateSession, 'id');
|
|
187
|
+
}
|
|
188
|
+
if (!note) {
|
|
189
|
+
note = translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
190
|
+
lng: language
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const alternates = getAlternates(filteredCorrectResponse);
|
|
194
|
+
const {
|
|
195
|
+
responseAreasToBeFilled,
|
|
196
|
+
possibleResponses,
|
|
197
|
+
hasUnplacedChoices
|
|
198
|
+
} = (0, _utils.getCompleteResponseDetails)(filteredCorrectResponse, normalizedQuestion.allowAlternateEnabled ? alternates : [], normalizedQuestion.choices);
|
|
199
|
+
const out = {
|
|
200
|
+
categories: categories || [],
|
|
201
|
+
categoriesPerRow: categoriesPerRow || 2,
|
|
202
|
+
maxChoicesPerCategory,
|
|
203
|
+
correctness: answerCorrectness,
|
|
204
|
+
choices: choices || [],
|
|
205
|
+
choicesLabel: choicesLabel || '',
|
|
206
|
+
choicesPosition,
|
|
207
|
+
disabled: mode !== 'gather',
|
|
208
|
+
feedback: fb,
|
|
209
|
+
lockChoiceOrder,
|
|
210
|
+
prompt: promptEnabled ? prompt : null,
|
|
211
|
+
rowLabels,
|
|
212
|
+
note,
|
|
213
|
+
env,
|
|
214
|
+
showNote: alternates && alternates.length > 0,
|
|
215
|
+
correctResponse: mode === 'evaluate' ? filteredCorrectResponse : undefined,
|
|
216
|
+
language,
|
|
217
|
+
extraCSSRules,
|
|
218
|
+
fontSizeFactor,
|
|
219
|
+
minRowHeight: minRowHeight,
|
|
220
|
+
autoplayAudioEnabled,
|
|
221
|
+
completeAudioEnabled,
|
|
222
|
+
customAudioButton,
|
|
223
|
+
possibleResponses,
|
|
224
|
+
responseAreasToBeFilled,
|
|
225
|
+
hasUnplacedChoices
|
|
226
|
+
};
|
|
227
|
+
if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {
|
|
228
|
+
out.rationale = rationaleEnabled ? rationale : null;
|
|
229
|
+
out.teacherInstructions = teacherInstructionsEnabled ? teacherInstructions : null;
|
|
230
|
+
} else {
|
|
231
|
+
out.rationale = null;
|
|
232
|
+
out.teacherInstructions = null;
|
|
233
|
+
}
|
|
234
|
+
resolve(out);
|
|
235
|
+
});
|
|
286
236
|
exports.model = model;
|
|
287
|
-
|
|
288
|
-
var outcome = function outcome(question, session, env) {
|
|
237
|
+
const outcome = (question, session, env) => {
|
|
289
238
|
if (env.mode !== 'evaluate') {
|
|
290
239
|
return Promise.reject(new Error('Can not call outcome when mode is not evaluate'));
|
|
291
240
|
} else {
|
|
292
|
-
return new Promise(
|
|
241
|
+
return new Promise(resolve => {
|
|
293
242
|
resolve({
|
|
294
243
|
score: getTotalScore(question, session, env),
|
|
295
|
-
empty: !session || (0, _isEmpty
|
|
244
|
+
empty: !session || (0, _isEmpty.default)(session)
|
|
296
245
|
});
|
|
297
246
|
});
|
|
298
247
|
}
|
|
299
248
|
};
|
|
300
|
-
|
|
301
249
|
exports.outcome = outcome;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
250
|
+
const createCorrectResponseSession = (question, env) => {
|
|
251
|
+
return new Promise(resolve => {
|
|
252
|
+
const {
|
|
253
|
+
mode,
|
|
254
|
+
role
|
|
255
|
+
} = env || {};
|
|
309
256
|
if (mode !== 'evaluate' && role === 'instructor') {
|
|
310
|
-
|
|
257
|
+
const {
|
|
258
|
+
correctResponse
|
|
259
|
+
} = question;
|
|
311
260
|
resolve({
|
|
312
261
|
answers: correctResponse,
|
|
313
262
|
id: 1
|
|
@@ -316,151 +265,125 @@ var createCorrectResponseSession = function createCorrectResponseSession(questio
|
|
|
316
265
|
return resolve(null);
|
|
317
266
|
}
|
|
318
267
|
});
|
|
319
|
-
}; // remove all html tags
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
exports.createCorrectResponseSession = createCorrectResponseSession;
|
|
323
|
-
|
|
324
|
-
var getInnerText = function getInnerText(html) {
|
|
325
|
-
return (html || '').replaceAll(/<[^>]*>/g, '');
|
|
326
|
-
}; // remove all html tags except img, iframe and source tag for audio
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
var getContent = function getContent(html) {
|
|
330
|
-
return (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
|
|
331
268
|
};
|
|
332
269
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
270
|
+
// remove all html tags
|
|
271
|
+
exports.createCorrectResponseSession = createCorrectResponseSession;
|
|
272
|
+
const getInnerText = html => (html || '').replaceAll(/<[^>]*>/g, '');
|
|
273
|
+
|
|
274
|
+
// remove all html tags except img, iframe and source tag for audio
|
|
275
|
+
const getContent = html => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
|
|
276
|
+
const validate = (model = {}, config = {}) => {
|
|
277
|
+
const {
|
|
278
|
+
categories,
|
|
279
|
+
choices,
|
|
280
|
+
correctResponse,
|
|
281
|
+
maxAnswerChoices
|
|
282
|
+
} = model;
|
|
283
|
+
const {
|
|
284
|
+
minChoices = 1,
|
|
285
|
+
minCategories = 1,
|
|
286
|
+
maxCategories = 12,
|
|
287
|
+
maxLengthPerChoice = 300,
|
|
288
|
+
maxLengthPerCategory = 150
|
|
289
|
+
} = config;
|
|
290
|
+
const reversedChoices = [...(choices || [])].reverse();
|
|
291
|
+
const errors = {};
|
|
292
|
+
const choicesErrors = {};
|
|
293
|
+
const categoriesErrors = {};
|
|
294
|
+
['teacherInstructions', 'prompt', 'rationale'].forEach(field => {
|
|
295
|
+
if (config[field]?.required && !getContent(model[field])) {
|
|
358
296
|
errors[field] = 'This field is required.';
|
|
359
297
|
}
|
|
360
298
|
});
|
|
361
|
-
(categories || []).forEach(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
299
|
+
(categories || []).forEach(category => {
|
|
300
|
+
const {
|
|
301
|
+
id,
|
|
302
|
+
label
|
|
303
|
+
} = category;
|
|
365
304
|
if (getInnerText(label).length > maxLengthPerCategory) {
|
|
366
|
-
categoriesErrors[id] =
|
|
305
|
+
categoriesErrors[id] = `Category labels should be no more than ${maxLengthPerCategory} characters long.`;
|
|
367
306
|
}
|
|
368
307
|
});
|
|
369
|
-
(reversedChoices || []).forEach(
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
308
|
+
(reversedChoices || []).forEach((choice, index) => {
|
|
309
|
+
const {
|
|
310
|
+
id,
|
|
311
|
+
content
|
|
312
|
+
} = choice;
|
|
373
313
|
if (getInnerText(content).length > maxLengthPerChoice) {
|
|
374
|
-
choicesErrors[id] =
|
|
314
|
+
choicesErrors[id] = `Tokens should be no more than ${maxLengthPerChoice} characters long.`;
|
|
375
315
|
}
|
|
376
|
-
|
|
377
316
|
if (!getContent(content)) {
|
|
378
317
|
choicesErrors[id] = 'Tokens should not be empty.';
|
|
379
318
|
} else {
|
|
380
|
-
|
|
381
|
-
return c.content === content;
|
|
382
|
-
});
|
|
383
|
-
|
|
319
|
+
const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.content === content);
|
|
384
320
|
if (identicalAnswer) {
|
|
385
321
|
choicesErrors[id] = 'Tokens content should be unique.';
|
|
386
322
|
}
|
|
387
323
|
}
|
|
388
324
|
});
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
325
|
+
const nbOfCategories = (categories || []).length;
|
|
326
|
+
const nbOfChoices = (choices || []).length;
|
|
392
327
|
if (nbOfCategories > maxCategories) {
|
|
393
|
-
errors.categoriesError =
|
|
328
|
+
errors.categoriesError = `No more than ${maxCategories} categories should be defined.`;
|
|
394
329
|
} else if (nbOfCategories < minCategories) {
|
|
395
|
-
errors.categoriesError =
|
|
330
|
+
errors.categoriesError = `There should be at least ${minCategories} category defined.`;
|
|
396
331
|
}
|
|
397
|
-
|
|
398
332
|
if (nbOfChoices < minChoices) {
|
|
399
|
-
errors.choicesError =
|
|
333
|
+
errors.choicesError = `There should be at least ${minChoices} choices defined.`;
|
|
400
334
|
} else if (nbOfChoices > maxAnswerChoices) {
|
|
401
|
-
errors.choicesError =
|
|
335
|
+
errors.choicesError = `No more than ${maxAnswerChoices} choices should be defined.`;
|
|
402
336
|
}
|
|
403
|
-
|
|
404
337
|
if (nbOfChoices && nbOfCategories) {
|
|
405
|
-
|
|
406
|
-
(correctResponse || []).forEach(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
338
|
+
let hasAssociations = false;
|
|
339
|
+
(correctResponse || []).forEach(response => {
|
|
340
|
+
const {
|
|
341
|
+
choices = [],
|
|
342
|
+
alternateResponses = []
|
|
343
|
+
} = response;
|
|
412
344
|
if (choices.length) {
|
|
413
345
|
hasAssociations = true;
|
|
414
346
|
} else {
|
|
415
|
-
alternateResponses.forEach(
|
|
347
|
+
alternateResponses.forEach(alternate => {
|
|
416
348
|
if ((alternate || []).length) {
|
|
417
349
|
hasAssociations = true;
|
|
418
350
|
}
|
|
419
351
|
});
|
|
420
352
|
}
|
|
421
353
|
});
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
(correctResponse || []).forEach(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
354
|
+
let duplicateAlternateIndex = -1;
|
|
355
|
+
let duplicateCategory = '';
|
|
356
|
+
(correctResponse || []).forEach(response => {
|
|
357
|
+
const {
|
|
358
|
+
choices = [],
|
|
359
|
+
alternateResponses = [],
|
|
360
|
+
category
|
|
361
|
+
} = response;
|
|
431
362
|
if (duplicateAlternateIndex === -1) {
|
|
432
363
|
duplicateAlternateIndex = (0, _utils.isCorrectResponseDuplicated)(choices, alternateResponses);
|
|
433
|
-
|
|
434
364
|
if (duplicateAlternateIndex === -1) {
|
|
435
365
|
duplicateAlternateIndex = (0, _utils.isAlternateDuplicated)(alternateResponses);
|
|
436
366
|
}
|
|
437
|
-
|
|
438
367
|
duplicateCategory = category;
|
|
439
368
|
}
|
|
440
369
|
});
|
|
441
|
-
|
|
442
370
|
if (duplicateAlternateIndex > -1) {
|
|
443
371
|
errors.duplicateAlternate = {
|
|
444
372
|
index: duplicateAlternateIndex,
|
|
445
373
|
category: duplicateCategory
|
|
446
374
|
};
|
|
447
375
|
}
|
|
448
|
-
|
|
449
376
|
if (!hasAssociations) {
|
|
450
377
|
errors.associationError = 'At least one token should be assigned to at least one category.';
|
|
451
378
|
}
|
|
452
379
|
}
|
|
453
|
-
|
|
454
|
-
if (!(0, _isEmpty["default"])(choicesErrors)) {
|
|
380
|
+
if (!(0, _isEmpty.default)(choicesErrors)) {
|
|
455
381
|
errors.choicesErrors = choicesErrors;
|
|
456
382
|
}
|
|
457
|
-
|
|
458
|
-
if (!(0, _isEmpty["default"])(categoriesErrors)) {
|
|
383
|
+
if (!(0, _isEmpty.default)(categoriesErrors)) {
|
|
459
384
|
errors.categoriesErrors = categoriesErrors;
|
|
460
385
|
}
|
|
461
|
-
|
|
462
386
|
return errors;
|
|
463
387
|
};
|
|
464
|
-
|
|
465
388
|
exports.validate = validate;
|
|
466
389
|
//# sourceMappingURL=index.js.map
|