@pie-element/categorize 6.6.0 → 6.6.1-beta.587

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.
Files changed (71) hide show
  1. package/CHANGELOG.md +538 -0
  2. package/configure/CHANGELOG.md +474 -0
  3. package/configure/lib/defaults.js +56 -5
  4. package/configure/lib/defaults.js.map +1 -1
  5. package/configure/lib/design/builder.js +8 -5
  6. package/configure/lib/design/builder.js.map +1 -1
  7. package/configure/lib/design/buttons.js +6 -4
  8. package/configure/lib/design/buttons.js.map +1 -1
  9. package/configure/lib/design/categories/RowLabel.js +68 -0
  10. package/configure/lib/design/categories/RowLabel.js.map +1 -0
  11. package/configure/lib/design/categories/alternateResponses.js +122 -18
  12. package/configure/lib/design/categories/alternateResponses.js.map +1 -1
  13. package/configure/lib/design/categories/category.js +53 -6
  14. package/configure/lib/design/categories/category.js.map +1 -1
  15. package/configure/lib/design/categories/choice-preview.js +19 -6
  16. package/configure/lib/design/categories/choice-preview.js.map +1 -1
  17. package/configure/lib/design/categories/droppable-placeholder.js +25 -5
  18. package/configure/lib/design/categories/droppable-placeholder.js.map +1 -1
  19. package/configure/lib/design/categories/index.js +172 -82
  20. package/configure/lib/design/categories/index.js.map +1 -1
  21. package/configure/lib/design/choices/choice.js +83 -13
  22. package/configure/lib/design/choices/choice.js.map +1 -1
  23. package/configure/lib/design/choices/config.js +10 -136
  24. package/configure/lib/design/choices/config.js.map +1 -1
  25. package/configure/lib/design/choices/index.js +89 -13
  26. package/configure/lib/design/choices/index.js.map +1 -1
  27. package/configure/lib/design/header.js +18 -6
  28. package/configure/lib/design/header.js.map +1 -1
  29. package/configure/lib/design/index.js +165 -50
  30. package/configure/lib/design/index.js.map +1 -1
  31. package/configure/lib/design/input-header.js +69 -11
  32. package/configure/lib/design/input-header.js.map +1 -1
  33. package/configure/lib/index.js +18 -4
  34. package/configure/lib/index.js.map +1 -1
  35. package/configure/lib/main.js +4 -2
  36. package/configure/lib/main.js.map +1 -1
  37. package/configure/lib/utils.js +27 -0
  38. package/configure/lib/utils.js.map +1 -0
  39. package/configure/package.json +9 -9
  40. package/controller/CHANGELOG.md +128 -0
  41. package/controller/lib/defaults.js +20 -1
  42. package/controller/lib/defaults.js.map +1 -1
  43. package/controller/lib/index.js +173 -30
  44. package/controller/lib/index.js.map +1 -1
  45. package/controller/lib/utils.js +60 -0
  46. package/controller/lib/utils.js.map +1 -0
  47. package/controller/package.json +4 -4
  48. package/docs/config-schema.json +181 -0
  49. package/docs/config-schema.json.md +141 -1
  50. package/docs/demo/config.js +2 -2
  51. package/docs/demo/generate.js +5 -8
  52. package/docs/demo/index.html +1 -1
  53. package/docs/pie-schema.json +63 -11
  54. package/docs/pie-schema.json.md +51 -11
  55. package/lib/categorize/categories.js +30 -24
  56. package/lib/categorize/categories.js.map +1 -1
  57. package/lib/categorize/category.js +15 -12
  58. package/lib/categorize/category.js.map +1 -1
  59. package/lib/categorize/choice.js +19 -12
  60. package/lib/categorize/choice.js.map +1 -1
  61. package/lib/categorize/choices.js +35 -16
  62. package/lib/categorize/choices.js.map +1 -1
  63. package/lib/categorize/droppable-placeholder.js +6 -4
  64. package/lib/categorize/droppable-placeholder.js.map +1 -1
  65. package/lib/categorize/grid-content.js +3 -3
  66. package/lib/categorize/grid-content.js.map +1 -1
  67. package/lib/categorize/index.js +71 -37
  68. package/lib/categorize/index.js.map +1 -1
  69. package/lib/index.js +4 -1
  70. package/lib/index.js.map +1 -1
  71. package/package.json +9 -8
@@ -5,16 +5,19 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
+ exports.outcome = exports.normalize = exports.model = exports.getTotalScore = exports.getPartialScore = exports.getCorrectness = exports.createDefaultModel = exports.createCorrectResponseSession = void 0;
8
9
  Object.defineProperty(exports, "score", {
9
10
  enumerable: true,
10
11
  get: function get() {
11
12
  return _categorize.score;
12
13
  }
13
14
  });
14
- exports.createCorrectResponseSession = exports.outcome = exports.model = exports.normalize = exports.createDefaultModel = exports.getCorrectness = exports.getTotalScore = exports.getPartialScore = void 0;
15
+ exports.validate = void 0;
15
16
 
16
17
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
17
18
 
19
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
20
+
18
21
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
19
22
 
20
23
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
@@ -25,13 +28,15 @@ var _categorize = require("@pie-lib/categorize");
25
28
 
26
29
  var _feedback = require("@pie-lib/feedback");
27
30
 
31
+ var _utils = require("./utils");
32
+
28
33
  var _controllerUtils = require("@pie-lib/controller-utils");
29
34
 
30
35
  var _defaults = _interopRequireDefault(require("./defaults"));
31
36
 
32
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
37
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
33
38
 
34
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
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; }
35
40
 
36
41
  var getPartialScore = function getPartialScore(correctResponse, builtCategories) {
37
42
  // in the resulted best scenario we make a sum with all the correct responses
@@ -71,6 +76,14 @@ var getPartialScore = function getPartialScore(correctResponse, builtCategories)
71
76
 
72
77
  exports.getPartialScore = getPartialScore;
73
78
 
79
+ var getAlternates = function getAlternates(correctResponse) {
80
+ return correctResponse.map(function (c) {
81
+ return c.alternateResponses;
82
+ }).filter(function (alternate) {
83
+ return alternate;
84
+ });
85
+ };
86
+
74
87
  var getTotalScore = function getTotalScore(question, session, env) {
75
88
  if (!session) {
76
89
  return 0;
@@ -98,16 +111,12 @@ var getTotalScore = function getTotalScore(question, session, env) {
98
111
  builtCategories = _buildState.categories,
99
112
  correct = _buildState.correct;
100
113
 
101
- var hasAlternates = correctResponse.map(function (c) {
102
- return c.alternateResponses;
103
- }).filter(function (alternate) {
104
- return alternate;
105
- });
114
+ var alternates = getAlternates(correctResponse);
106
115
 
107
116
  var enabled = _controllerUtils.partialScoring.enabled(question, env); // if there are any alternates, there will be no partial scoring!
108
117
 
109
118
 
110
- if (enabled && !hasAlternates.length) {
119
+ if (enabled && !alternates.length) {
111
120
  // we apply partial scoring
112
121
  return getPartialScore(correctResponse, builtCategories);
113
122
  } // else we apply dichotomous
@@ -148,13 +157,7 @@ var createDefaultModel = function createDefaultModel() {
148
157
  exports.createDefaultModel = createDefaultModel;
149
158
 
150
159
  var normalize = function normalize(question) {
151
- return _objectSpread({
152
- feedbackEnabled: true,
153
- rationaleEnabled: true,
154
- promptEnabled: true,
155
- teacherInstructionsEnabled: true,
156
- studentInstructionsEnabled: true
157
- }, question);
160
+ return _objectSpread(_objectSpread({}, _defaults["default"]), question);
158
161
  };
159
162
  /**
160
163
  *
@@ -170,7 +173,7 @@ exports.normalize = normalize;
170
173
  var model = function model(question, session, env, updateSession) {
171
174
  return new Promise( /*#__PURE__*/function () {
172
175
  var _ref6 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(resolve) {
173
- var normalizedQuestion, answerCorrectness, _ref7, mode, role, categories, categoriesPerRow, choicesPerRow, choicesLabel, choicesPosition, correctResponse, feedback, feedbackEnabled, promptEnabled, prompt, removeTilesAfterPlacing, rowLabels, rationaleEnabled, rationale, teacherInstructionsEnabled, teacherInstructions, choices, fb, lockChoiceOrder, out;
176
+ var normalizedQuestion, answerCorrectness, _ref7, mode, role, categories, categoriesPerRow, choicesLabel, choicesPosition, correctResponse, feedback, feedbackEnabled, promptEnabled, prompt, rowLabels, rationaleEnabled, rationale, note, teacherInstructionsEnabled, teacherInstructions, choices, fb, lockChoiceOrder, filteredCorrectResponse, alternates, out;
174
177
 
175
178
  return _regenerator["default"].wrap(function _callee$(_context) {
176
179
  while (1) {
@@ -183,49 +186,59 @@ var model = function model(question, session, env, updateSession) {
183
186
  case 3:
184
187
  answerCorrectness = _context.sent;
185
188
  _ref7 = env || {}, mode = _ref7.mode, role = _ref7.role;
186
- categories = normalizedQuestion.categories, categoriesPerRow = normalizedQuestion.categoriesPerRow, choicesPerRow = normalizedQuestion.choicesPerRow, choicesLabel = normalizedQuestion.choicesLabel, choicesPosition = normalizedQuestion.choicesPosition, correctResponse = normalizedQuestion.correctResponse, feedback = normalizedQuestion.feedback, feedbackEnabled = normalizedQuestion.feedbackEnabled, promptEnabled = normalizedQuestion.promptEnabled, prompt = normalizedQuestion.prompt, removeTilesAfterPlacing = normalizedQuestion.removeTilesAfterPlacing, rowLabels = normalizedQuestion.rowLabels, rationaleEnabled = normalizedQuestion.rationaleEnabled, rationale = normalizedQuestion.rationale, teacherInstructionsEnabled = normalizedQuestion.teacherInstructionsEnabled, teacherInstructions = normalizedQuestion.teacherInstructions;
189
+ categories = normalizedQuestion.categories, categoriesPerRow = normalizedQuestion.categoriesPerRow, choicesLabel = normalizedQuestion.choicesLabel, choicesPosition = normalizedQuestion.choicesPosition, correctResponse = normalizedQuestion.correctResponse, feedback = normalizedQuestion.feedback, feedbackEnabled = normalizedQuestion.feedbackEnabled, promptEnabled = normalizedQuestion.promptEnabled, prompt = normalizedQuestion.prompt, rowLabels = normalizedQuestion.rowLabels, rationaleEnabled = normalizedQuestion.rationaleEnabled, rationale = normalizedQuestion.rationale, note = normalizedQuestion.note, teacherInstructionsEnabled = normalizedQuestion.teacherInstructionsEnabled, teacherInstructions = normalizedQuestion.teacherInstructions;
187
190
  choices = normalizedQuestion.choices;
188
191
  lockChoiceOrder = (0, _controllerUtils.lockChoices)(normalizedQuestion, session, env);
192
+ filteredCorrectResponse = correctResponse.map(function (response) {
193
+ var filteredChoices = (response.choices || []).filter(function (choice) {
194
+ return choice !== 'null';
195
+ });
196
+ return _objectSpread(_objectSpread({}, response), {}, {
197
+ choices: filteredChoices
198
+ });
199
+ });
189
200
 
190
201
  if (!(mode === 'evaluate' && feedbackEnabled)) {
191
- _context.next = 12;
202
+ _context.next = 13;
192
203
  break;
193
204
  }
194
205
 
195
- _context.next = 11;
206
+ _context.next = 12;
196
207
  return (0, _feedback.getFeedbackForCorrectness)(answerCorrectness, feedback);
197
208
 
198
- case 11:
209
+ case 12:
199
210
  fb = _context.sent;
200
211
 
201
- case 12:
212
+ case 13:
202
213
  if (lockChoiceOrder) {
203
- _context.next = 16;
214
+ _context.next = 17;
204
215
  break;
205
216
  }
206
217
 
207
- _context.next = 15;
218
+ _context.next = 16;
208
219
  return (0, _controllerUtils.getShuffledChoices)(choices, session, updateSession, 'id');
209
220
 
210
- case 15:
221
+ case 16:
211
222
  choices = _context.sent;
212
223
 
213
- case 16:
224
+ case 17:
225
+ alternates = getAlternates(filteredCorrectResponse);
214
226
  out = {
215
227
  categories: categories || [],
216
228
  categoriesPerRow: categoriesPerRow || 2,
217
229
  correctness: answerCorrectness,
218
230
  choices: choices || [],
219
231
  choicesLabel: choicesLabel || '',
220
- choicesPerRow: choicesPerRow || 2,
221
232
  choicesPosition: choicesPosition,
222
233
  disabled: mode !== 'gather',
223
234
  feedback: fb,
224
235
  lockChoiceOrder: lockChoiceOrder,
225
236
  prompt: promptEnabled ? prompt : null,
226
- removeTilesAfterPlacing: removeTilesAfterPlacing,
227
237
  rowLabels: rowLabels,
228
- correctResponse: mode === 'evaluate' ? correctResponse : undefined
238
+ note: note,
239
+ env: env,
240
+ showNote: alternates && alternates.length > 0,
241
+ correctResponse: mode === 'evaluate' ? filteredCorrectResponse : undefined
229
242
  };
230
243
 
231
244
  if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {
@@ -238,7 +251,7 @@ var model = function model(question, session, env, updateSession) {
238
251
 
239
252
  resolve(out);
240
253
 
241
- case 19:
254
+ case 21:
242
255
  case "end":
243
256
  return _context.stop();
244
257
  }
@@ -288,4 +301,134 @@ var createCorrectResponseSession = function createCorrectResponseSession(questio
288
301
  };
289
302
 
290
303
  exports.createCorrectResponseSession = createCorrectResponseSession;
304
+
305
+ var validate = function validate() {
306
+ var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
307
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
308
+ var categories = model.categories,
309
+ choices = model.choices,
310
+ correctResponse = model.correctResponse;
311
+ var _config$minChoices = config.minChoices,
312
+ minChoices = _config$minChoices === void 0 ? 1 : _config$minChoices,
313
+ _config$maxChoices = config.maxChoices,
314
+ maxChoices = _config$maxChoices === void 0 ? 15 : _config$maxChoices,
315
+ _config$minCategories = config.minCategories,
316
+ minCategories = _config$minCategories === void 0 ? 1 : _config$minCategories,
317
+ _config$maxCategories = config.maxCategories,
318
+ maxCategories = _config$maxCategories === void 0 ? 12 : _config$maxCategories,
319
+ _config$maxLengthPerC = config.maxLengthPerChoice,
320
+ maxLengthPerChoice = _config$maxLengthPerC === void 0 ? 300 : _config$maxLengthPerC,
321
+ _config$maxLengthPerC2 = config.maxLengthPerCategory,
322
+ maxLengthPerCategory = _config$maxLengthPerC2 === void 0 ? 150 : _config$maxLengthPerC2;
323
+ var reversedChoices = (0, _toConsumableArray2["default"])(choices || []).reverse();
324
+ var errors = {};
325
+ var choicesErrors = {};
326
+ var categoriesErrors = {};
327
+ (categories || []).forEach(function (category) {
328
+ var id = category.id,
329
+ label = category.label;
330
+ var parsedLabel = label.replace(/<(?:.|\n)*?>/gm, '');
331
+
332
+ if (parsedLabel.length > maxLengthPerCategory) {
333
+ categoriesErrors[id] = "Category labels should be no more than ".concat(maxLengthPerCategory, " characters long.");
334
+ }
335
+ });
336
+ (reversedChoices || []).forEach(function (choice, index) {
337
+ var id = choice.id,
338
+ content = choice.content;
339
+ var parsedContent = content.replace(/<(?:.|\n)*?>/gm, '');
340
+
341
+ if (parsedContent.length > maxLengthPerChoice) {
342
+ choicesErrors[id] = "Tokens should be no more than ".concat(maxLengthPerChoice, " characters long.");
343
+ }
344
+
345
+ if (content === '' || content === '<div></div>') {
346
+ choicesErrors[id] = 'Tokens should not be empty.';
347
+ } else {
348
+ var identicalAnswer = reversedChoices.slice(index + 1).some(function (c) {
349
+ return c.content === content;
350
+ });
351
+
352
+ if (identicalAnswer) {
353
+ choicesErrors[id] = 'Tokens content should be unique.';
354
+ }
355
+ }
356
+ });
357
+ var nbOfCategories = (categories || []).length;
358
+ var nbOfChoices = (choices || []).length;
359
+
360
+ if (nbOfCategories > maxCategories) {
361
+ errors.categoriesError = "No more than ".concat(maxCategories, " categories should be defined.");
362
+ } else if (nbOfCategories < minCategories) {
363
+ errors.categoriesError = "There should be at least ".concat(minCategories, " category defined.");
364
+ }
365
+
366
+ if (nbOfChoices < minChoices) {
367
+ errors.choicesError = "There should be at least ".concat(minChoices, " choices defined.");
368
+ } else if (nbOfChoices > maxChoices) {
369
+ errors.choicesError = "No more than ".concat(maxChoices, " choices should be defined.");
370
+ }
371
+
372
+ if (nbOfChoices && nbOfCategories) {
373
+ var hasAssociations = false;
374
+ (correctResponse || []).forEach(function (response) {
375
+ var _response$choices = response.choices,
376
+ choices = _response$choices === void 0 ? [] : _response$choices,
377
+ _response$alternateRe = response.alternateResponses,
378
+ alternateResponses = _response$alternateRe === void 0 ? [] : _response$alternateRe;
379
+
380
+ if (choices.length) {
381
+ hasAssociations = true;
382
+ } else {
383
+ alternateResponses.forEach(function (alternate) {
384
+ if ((alternate || []).length) {
385
+ hasAssociations = true;
386
+ }
387
+ });
388
+ }
389
+ });
390
+ var duplicateAlternateIndex = -1;
391
+ var duplicateCategory = '';
392
+ (correctResponse || []).forEach(function (response) {
393
+ var _response$choices2 = response.choices,
394
+ choices = _response$choices2 === void 0 ? [] : _response$choices2,
395
+ _response$alternateRe2 = response.alternateResponses,
396
+ alternateResponses = _response$alternateRe2 === void 0 ? [] : _response$alternateRe2,
397
+ category = response.category;
398
+
399
+ if (duplicateAlternateIndex === -1) {
400
+ duplicateAlternateIndex = (0, _utils.isCorrectResponseDuplicated)(choices, alternateResponses);
401
+
402
+ if (duplicateAlternateIndex === -1) {
403
+ duplicateAlternateIndex = (0, _utils.isAlternateDuplicated)(alternateResponses);
404
+ }
405
+
406
+ duplicateCategory = category;
407
+ }
408
+ });
409
+
410
+ if (duplicateAlternateIndex > -1) {
411
+ errors.duplicateAlternate = {
412
+ index: duplicateAlternateIndex,
413
+ category: duplicateCategory
414
+ };
415
+ }
416
+
417
+ if (!hasAssociations) {
418
+ errors.associationError = 'At least one token should be assigned to at least one category.';
419
+ }
420
+ }
421
+
422
+ if (!(0, _isEmpty["default"])(choicesErrors)) {
423
+ errors.choicesErrors = choicesErrors;
424
+ }
425
+
426
+ if (!(0, _isEmpty["default"])(categoriesErrors)) {
427
+ errors.categoriesErrors = categoriesErrors;
428
+ }
429
+
430
+ return errors;
431
+ };
432
+
433
+ exports.validate = validate;
291
434
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"names":["getPartialScore","correctResponse","builtCategories","reduce","acc","choices","placements","length","score","filter","ch","correct","maxScore","extraPlacements","totalScore","parseFloat","toFixed","getTotalScore","question","session","env","Object","keys","categories","answers","hasAlternates","map","c","alternateResponses","alternate","enabled","partialScoring","getCorrectness","Promise","resolve","mode","undefined","createDefaultModel","model","defaults","normalize","feedbackEnabled","rationaleEnabled","promptEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","updateSession","normalizedQuestion","answerCorrectness","role","categoriesPerRow","choicesPerRow","choicesLabel","choicesPosition","feedback","prompt","removeTilesAfterPlacing","rowLabels","rationale","teacherInstructions","lockChoiceOrder","fb","out","correctness","disabled","outcome","reject","Error","empty","createCorrectResponseSession","id"],"mappings":"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","sourcesContent":["import isEmpty from 'lodash/isEmpty';\nimport { buildState, score } from '@pie-lib/categorize';\nimport { getFeedbackForCorrectness } from '@pie-lib/feedback';\nimport {\n lockChoices,\n getShuffledChoices,\n partialScoring,\n} from '@pie-lib/controller-utils';\nimport defaults from './defaults';\n\n// eslint-disable-next-line no-console\n\nexport { score };\n\nexport const getPartialScore = (correctResponse, builtCategories) => {\n // in the resulted best scenario we make a sum with all the correct responses\n // and all the placements\n const { placements, score } = builtCategories.reduce(\n (acc, { choices = [] }) => ({\n placements: acc.placements + choices.length,\n score: acc.score + choices.filter((ch) => ch.correct).length,\n }),\n { placements: 0, score: 0 }\n );\n\n // in the correct response, we make a sum of the max possible score\n const { maxScore } = correctResponse.reduce(\n (acc, { choices }) => ({\n maxScore: acc.maxScore + choices.length,\n }),\n { maxScore: 0 }\n );\n\n // if there are any extra placements, we subtract from the obtained score\n const extraPlacements = placements > maxScore ? placements - maxScore : 0;\n const totalScore = (score - extraPlacements) / maxScore;\n\n return totalScore < 0 ? 0 : parseFloat(totalScore.toFixed(2));\n};\n\nexport const getTotalScore = (question, session, env) => {\n if (!session) {\n return 0;\n }\n\n if (Object.keys(session).length === 0) {\n return 0;\n }\n const { categories, choices } = question || {};\n let { correctResponse } = question || {};\n let { answers } = session || {};\n answers = answers || [];\n correctResponse = correctResponse || [];\n\n // this function is used in pie-ui/categorize as well, in order to get the best scenario\n // so we get the best scenario and calculate the score\n const { categories: builtCategories, correct } = buildState(\n categories,\n choices,\n answers,\n correctResponse\n );\n\n const hasAlternates = correctResponse\n .map((c) => c.alternateResponses)\n .filter((alternate) => alternate);\n const enabled = partialScoring.enabled(question, env);\n\n // if there are any alternates, there will be no partial scoring!\n if (enabled && !hasAlternates.length) {\n // we apply partial scoring\n return getPartialScore(correctResponse, builtCategories);\n }\n\n // else we apply dichotomous\n return correct ? 1 : 0;\n};\n\nexport const getCorrectness = (question, session, env) => {\n return new Promise((resolve) => {\n if (env.mode === 'evaluate') {\n const score = getTotalScore(question, session, env);\n if (score === 1) {\n resolve('correct');\n } else if (score === 0) {\n resolve('incorrect');\n } else {\n resolve('partially-correct');\n }\n } else {\n resolve(undefined);\n }\n });\n};\n\nexport const createDefaultModel = (model = {}) =>\n new Promise((resolve) => {\n resolve({\n ...defaults,\n ...model,\n });\n });\n\nexport const normalize = (question) => ({\n feedbackEnabled: true,\n rationaleEnabled: true,\n promptEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n ...question,\n});\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 const model = (question, session, env, updateSession) =>\n new Promise(async (resolve) => {\n const normalizedQuestion = normalize(question);\n const answerCorrectness = await getCorrectness(normalizedQuestion, session, env);\n\n const { mode, role } = env || {};\n\n const {\n categories,\n categoriesPerRow,\n choicesPerRow,\n choicesLabel,\n choicesPosition,\n correctResponse,\n feedback,\n feedbackEnabled,\n promptEnabled,\n prompt,\n removeTilesAfterPlacing,\n rowLabels,\n rationaleEnabled,\n rationale,\n teacherInstructionsEnabled,\n teacherInstructions,\n } = normalizedQuestion;\n let { choices } = normalizedQuestion;\n let fb;\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n if (mode === 'evaluate' && feedbackEnabled) {\n fb = await getFeedbackForCorrectness(\n answerCorrectness,\n feedback\n );\n }\n\n if (!lockChoiceOrder) {\n choices = await getShuffledChoices(choices, session, updateSession, 'id');\n }\n\n const out = {\n categories: categories || [],\n categoriesPerRow: categoriesPerRow || 2,\n correctness: answerCorrectness,\n choices: choices || [],\n choicesLabel: choicesLabel || '',\n choicesPerRow: choicesPerRow || 2,\n choicesPosition,\n disabled: mode !== 'gather',\n feedback: fb,\n lockChoiceOrder,\n prompt: promptEnabled ? prompt : null,\n removeTilesAfterPlacing,\n rowLabels,\n correctResponse: mode === 'evaluate' ? correctResponse : undefined,\n };\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.rationale = rationaleEnabled ? rationale : null;\n out.teacherInstructions = teacherInstructionsEnabled\n ? teacherInstructions\n : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n\nexport const outcome = (question, session, env) => {\n if (env.mode !== 'evaluate') {\n return Promise.reject(\n new Error('Can not call outcome when mode is not evaluate')\n );\n } else {\n return new Promise((resolve) => {\n resolve({\n score: getTotalScore(question, session, env),\n empty: !session || isEmpty(session),\n });\n });\n }\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n const { mode, role } = env || {};\n\n if (mode !== 'evaluate' && role === 'instructor') {\n const { correctResponse } = question;\n\n resolve({ answers: correctResponse, id: 1 });\n } else {\n return resolve(null);\n }\n });\n};\n"],"file":"index.js"}
1
+ {"version":3,"sources":["../src/index.js"],"names":["getPartialScore","correctResponse","builtCategories","reduce","acc","choices","placements","length","score","filter","ch","correct","maxScore","extraPlacements","totalScore","parseFloat","toFixed","getAlternates","map","c","alternateResponses","alternate","getTotalScore","question","session","env","Object","keys","categories","answers","alternates","enabled","partialScoring","getCorrectness","Promise","resolve","mode","undefined","createDefaultModel","model","defaults","normalize","updateSession","normalizedQuestion","answerCorrectness","role","categoriesPerRow","choicesLabel","choicesPosition","feedback","feedbackEnabled","promptEnabled","prompt","rowLabels","rationaleEnabled","rationale","note","teacherInstructionsEnabled","teacherInstructions","lockChoiceOrder","filteredCorrectResponse","response","filteredChoices","choice","fb","out","correctness","disabled","showNote","outcome","reject","Error","empty","createCorrectResponseSession","id","validate","config","minChoices","maxChoices","minCategories","maxCategories","maxLengthPerChoice","maxLengthPerCategory","reversedChoices","reverse","errors","choicesErrors","categoriesErrors","forEach","category","label","parsedLabel","replace","index","content","parsedContent","identicalAnswer","slice","some","nbOfCategories","nbOfChoices","categoriesError","choicesError","hasAssociations","duplicateAlternateIndex","duplicateCategory","duplicateAlternate","associationError"],"mappings":"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","sourcesContent":["import isEmpty from 'lodash/isEmpty';\nimport { buildState, score } from '@pie-lib/categorize';\nimport { getFeedbackForCorrectness } from '@pie-lib/feedback';\nimport { isAlternateDuplicated, isCorrectResponseDuplicated } from './utils';\nimport { lockChoices, getShuffledChoices, partialScoring } from '@pie-lib/controller-utils';\nimport defaults from './defaults';\n\n// eslint-disable-next-line no-console\n\nexport { score };\n\nexport const getPartialScore = (correctResponse, builtCategories) => {\n // in the resulted best scenario we make a sum with all the correct responses\n // and all the placements\n const { placements, score } = builtCategories.reduce(\n (acc, { choices = [] }) => ({\n placements: acc.placements + choices.length,\n score: acc.score + choices.filter((ch) => ch.correct).length,\n }),\n { placements: 0, score: 0 },\n );\n\n // in the correct response, we make a sum of the max possible score\n const { maxScore } = correctResponse.reduce(\n (acc, { choices }) => ({\n maxScore: acc.maxScore + choices.length,\n }),\n { maxScore: 0 },\n );\n\n // if there are any extra placements, we subtract from the obtained score\n const extraPlacements = placements > maxScore ? placements - maxScore : 0;\n const totalScore = (score - extraPlacements) / maxScore;\n\n return totalScore < 0 ? 0 : parseFloat(totalScore.toFixed(2));\n};\n\nconst getAlternates = (correctResponse) =>\n correctResponse.map((c) => c.alternateResponses).filter((alternate) => alternate);\n\nexport const getTotalScore = (question, session, env) => {\n if (!session) {\n return 0;\n }\n\n if (Object.keys(session).length === 0) {\n return 0;\n }\n const { categories, choices } = question || {};\n let { correctResponse } = question || {};\n let { answers } = session || {};\n answers = answers || [];\n correctResponse = correctResponse || [];\n\n // this function is used in pie-ui/categorize as well, in order to get the best scenario\n // so we get the best scenario and calculate the score\n const { categories: builtCategories, correct } = buildState(categories, choices, answers, correctResponse);\n\n const alternates = getAlternates(correctResponse);\n const enabled = partialScoring.enabled(question, env);\n\n // if there are any alternates, there will be no partial scoring!\n if (enabled && !alternates.length) {\n // we apply partial scoring\n return getPartialScore(correctResponse, builtCategories);\n }\n\n // else we apply dichotomous\n return correct ? 1 : 0;\n};\n\nexport const getCorrectness = (question, session, env) => {\n return new Promise((resolve) => {\n if (env.mode === 'evaluate') {\n const score = getTotalScore(question, session, env);\n if (score === 1) {\n resolve('correct');\n } else if (score === 0) {\n resolve('incorrect');\n } else {\n resolve('partially-correct');\n }\n } else {\n resolve(undefined);\n }\n });\n};\n\nexport const createDefaultModel = (model = {}) =>\n new Promise((resolve) => {\n resolve({\n ...defaults,\n ...model,\n });\n });\n\nexport const normalize = (question) => ({\n ...defaults,\n ...question,\n});\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 const model = (question, session, env, updateSession) =>\n new Promise(async (resolve) => {\n const normalizedQuestion = normalize(question);\n const answerCorrectness = await getCorrectness(normalizedQuestion, session, env);\n\n const { mode, role } = env || {};\n\n const {\n categories,\n categoriesPerRow,\n choicesLabel,\n choicesPosition,\n correctResponse,\n feedback,\n feedbackEnabled,\n promptEnabled,\n prompt,\n rowLabels,\n rationaleEnabled,\n rationale,\n note,\n teacherInstructionsEnabled,\n teacherInstructions,\n } = normalizedQuestion;\n let { choices } = normalizedQuestion;\n let fb;\n\n const lockChoiceOrder = lockChoices(normalizedQuestion, session, env);\n\n const filteredCorrectResponse = correctResponse.map((response) => {\n const filteredChoices = (response.choices || []).filter((choice) => choice !== 'null');\n return { ...response, choices: filteredChoices };\n });\n\n if (mode === 'evaluate' && feedbackEnabled) {\n fb = await getFeedbackForCorrectness(answerCorrectness, feedback);\n }\n\n if (!lockChoiceOrder) {\n choices = await getShuffledChoices(choices, session, updateSession, 'id');\n }\n\n const alternates = getAlternates(filteredCorrectResponse);\n const out = {\n categories: categories || [],\n categoriesPerRow: categoriesPerRow || 2,\n correctness: answerCorrectness,\n choices: choices || [],\n choicesLabel: choicesLabel || '',\n choicesPosition,\n disabled: mode !== 'gather',\n feedback: fb,\n lockChoiceOrder,\n prompt: promptEnabled ? prompt : null,\n rowLabels,\n note,\n env,\n showNote: alternates && alternates.length > 0,\n correctResponse: mode === 'evaluate' ? filteredCorrectResponse : undefined,\n };\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n out.rationale = rationaleEnabled ? rationale : null;\n out.teacherInstructions = teacherInstructionsEnabled ? teacherInstructions : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n\nexport const outcome = (question, session, env) => {\n if (env.mode !== 'evaluate') {\n return Promise.reject(new Error('Can not call outcome when mode is not evaluate'));\n } else {\n return new Promise((resolve) => {\n resolve({\n score: getTotalScore(question, session, env),\n empty: !session || isEmpty(session),\n });\n });\n }\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n const { mode, role } = env || {};\n\n if (mode !== 'evaluate' && role === 'instructor') {\n const { correctResponse } = question;\n\n resolve({ answers: correctResponse, id: 1 });\n } else {\n return resolve(null);\n }\n });\n};\n\nexport const validate = (model = {}, config = {}) => {\n const { categories, choices, correctResponse } = model;\n const { minChoices = 1, maxChoices = 15, minCategories = 1, maxCategories = 12, maxLengthPerChoice = 300, maxLengthPerCategory = 150 } = config;\n const reversedChoices = [ ...choices || []].reverse();\n const errors = {};\n const choicesErrors = {};\n const categoriesErrors = {};\n\n (categories || []).forEach((category) => {\n const {id, label} = category;\n const parsedLabel = label.replace(/<(?:.|\\n)*?>/gm, '');\n if (parsedLabel.length > maxLengthPerCategory){\n categoriesErrors[id] = `Category labels should be no more than ${maxLengthPerCategory} characters long.`;\n }\n });\n\n (reversedChoices || []).forEach((choice, index) => {\n const { id, content } = choice;\n const parsedContent = content.replace(/<(?:.|\\n)*?>/gm, '');\n if (parsedContent.length > maxLengthPerChoice){\n choicesErrors[id] = `Tokens should be no more than ${maxLengthPerChoice} characters long.`;\n }\n if (content === '' || content === '<div></div>') {\n choicesErrors[id] = 'Tokens should not be empty.';\n } else {\n const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.content === content);\n\n if (identicalAnswer) {\n choicesErrors[id] = 'Tokens content should be unique.';\n }\n }\n });\n\n const nbOfCategories = (categories || []).length;\n const nbOfChoices = (choices || []).length;\n\n if (nbOfCategories > maxCategories) {\n errors.categoriesError = `No more than ${maxCategories} categories should be defined.`;\n } else if (nbOfCategories < minCategories) {\n errors.categoriesError = `There should be at least ${minCategories} category defined.`;\n }\n\n if (nbOfChoices < minChoices) {\n errors.choicesError = `There should be at least ${minChoices} choices defined.`;\n } else if (nbOfChoices > maxChoices) {\n errors.choicesError = `No more than ${maxChoices} choices should be defined.`;\n }\n\n if (nbOfChoices && nbOfCategories) {\n let hasAssociations = false;\n\n (correctResponse || []).forEach(response => {\n const { choices = [], alternateResponses = [] } = response;\n\n if (choices.length) {\n hasAssociations = true;\n } else {\n alternateResponses.forEach(alternate => {\n if ((alternate || []).length) {\n hasAssociations = true;\n }\n });\n }\n });\n\n let duplicateAlternateIndex = -1;\n let duplicateCategory = '';\n (correctResponse || []).forEach(response => {\n const { choices = [], alternateResponses = [], category } = response;\n if (duplicateAlternateIndex === -1) {\n duplicateAlternateIndex = isCorrectResponseDuplicated(choices,alternateResponses);\n if (duplicateAlternateIndex === -1) {\n duplicateAlternateIndex = isAlternateDuplicated(alternateResponses);\n }\n duplicateCategory = category;\n }\n });\n\n if (duplicateAlternateIndex > -1) {\n errors.duplicateAlternate = {index:duplicateAlternateIndex, category:duplicateCategory};\n }\n\n if (!hasAssociations) {\n errors.associationError = 'At least one token should be assigned to at least one category.';\n }\n }\n\n if (!isEmpty(choicesErrors)) {\n errors.choicesErrors = choicesErrors;\n }\n\n if (!isEmpty(categoriesErrors)) {\n errors.categoriesErrors = categoriesErrors;\n }\n return errors;\n};\n"],"file":"index.js"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.multiplePlacements = exports.isCorrectResponseDuplicated = exports.isAlternateDuplicated = void 0;
9
+
10
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
+
12
+ // used in configure too, for consistency modify it there too
13
+ var multiplePlacements = {
14
+ enabled: 'Yes',
15
+ disabled: 'No',
16
+ perChoice: 'Set Per Choice'
17
+ }; // used to validate the config
18
+
19
+ exports.multiplePlacements = multiplePlacements;
20
+
21
+ var isCorrectResponseDuplicated = function isCorrectResponseDuplicated(choices, alternate) {
22
+ if (choices.length < 1 || alternate.length < 1) {
23
+ return -1;
24
+ }
25
+
26
+ var stringChoices = JSON.stringify(choices.sort());
27
+ var stringAlternate = alternate.reduce(function (total, current) {
28
+ return current.length > 0 ? [].concat((0, _toConsumableArray2["default"])(total), [JSON.stringify(current.sort())]) : total;
29
+ }, []);
30
+ var foundIndexDuplicate = stringAlternate.findIndex(function (alternate) {
31
+ return alternate.length && alternate === stringChoices;
32
+ });
33
+ return foundIndexDuplicate;
34
+ };
35
+
36
+ exports.isCorrectResponseDuplicated = isCorrectResponseDuplicated;
37
+
38
+ var isAlternateDuplicated = function isAlternateDuplicated(alternate) {
39
+ if (alternate.length <= 1) {
40
+ return -1;
41
+ }
42
+
43
+ var elementSet = new Set();
44
+ var stringAlternate = alternate.reduce(function (total, current) {
45
+ return current.length > 0 ? [].concat((0, _toConsumableArray2["default"])(total), [JSON.stringify(current.sort())]) : total;
46
+ }, []);
47
+
48
+ for (var i = 0; i < stringAlternate.length; i++) {
49
+ if (elementSet.has(stringAlternate[i]) && stringAlternate[i]) {
50
+ return i;
51
+ }
52
+
53
+ elementSet.add(stringAlternate[i]);
54
+ }
55
+
56
+ return -1;
57
+ };
58
+
59
+ exports.isAlternateDuplicated = isAlternateDuplicated;
60
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.js"],"names":["multiplePlacements","enabled","disabled","perChoice","isCorrectResponseDuplicated","choices","alternate","length","stringChoices","JSON","stringify","sort","stringAlternate","reduce","total","current","foundIndexDuplicate","findIndex","isAlternateDuplicated","elementSet","Set","i","has","add"],"mappings":";;;;;;;;;;;AAAA;AACO,IAAMA,kBAAkB,GAAG;AAAEC,EAAAA,OAAO,EAAE,KAAX;AAAkBC,EAAAA,QAAQ,EAAE,IAA5B;AAAkCC,EAAAA,SAAS,EAAE;AAA7C,CAA3B,C,CAEP;;;;AACO,IAAMC,2BAA2B,GAAG,SAA9BA,2BAA8B,CAACC,OAAD,EAASC,SAAT,EAAuB;AAC9D,MAAID,OAAO,CAACE,MAAR,GAAiB,CAAjB,IAAsBD,SAAS,CAACC,MAAV,GAAmB,CAA7C,EAA+C;AAC3C,WAAO,CAAC,CAAR;AACH;;AACD,MAAMC,aAAa,GAAIC,IAAI,CAACC,SAAL,CAAeL,OAAO,CAACM,IAAR,EAAf,CAAvB;AACA,MAAMC,eAAe,GAAGN,SAAS,CAACO,MAAV,CAAiB,UAACC,KAAD,EAAQC,OAAR;AAAA,WAAoBA,OAAO,CAACR,MAAR,GAAiB,CAAjB,iDAAyBO,KAAzB,IAAgCL,IAAI,CAACC,SAAL,CAAeK,OAAO,CAACJ,IAAR,EAAf,CAAhC,KAAkEG,KAAtF;AAAA,GAAjB,EAA8G,EAA9G,CAAxB;AACA,MAAME,mBAAmB,GAAGJ,eAAe,CAACK,SAAhB,CAA0B,UAAAX,SAAS;AAAA,WAAIA,SAAS,CAACC,MAAV,IAAqBD,SAAS,KAAKE,aAAvC;AAAA,GAAnC,CAA5B;AACA,SAAOQ,mBAAP;AACH,CARM;;;;AAUA,IAAME,qBAAqB,GAAG,SAAxBA,qBAAwB,CAACZ,SAAD,EAAe;AAChD,MAAIA,SAAS,CAACC,MAAV,IAAoB,CAAxB,EAA0B;AACtB,WAAO,CAAC,CAAR;AACH;;AACD,MAAMY,UAAU,GAAG,IAAIC,GAAJ,EAAnB;AACA,MAAMR,eAAe,GAAGN,SAAS,CAACO,MAAV,CAAiB,UAACC,KAAD,EAAQC,OAAR;AAAA,WAAoBA,OAAO,CAACR,MAAR,GAAiB,CAAjB,iDAAyBO,KAAzB,IAAgCL,IAAI,CAACC,SAAL,CAAeK,OAAO,CAACJ,IAAR,EAAf,CAAhC,KAAkEG,KAAtF;AAAA,GAAjB,EAA8G,EAA9G,CAAxB;;AACA,OAAK,IAAIO,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGT,eAAe,CAACL,MAApC,EAA4Cc,CAAC,EAA7C,EAAiD;AAC7C,QAAIF,UAAU,CAACG,GAAX,CAAeV,eAAe,CAACS,CAAD,CAA9B,KAAsCT,eAAe,CAACS,CAAD,CAAzD,EAA8D;AAC1D,aAAOA,CAAP;AACH;;AACDF,IAAAA,UAAU,CAACI,GAAX,CAAeX,eAAe,CAACS,CAAD,CAA9B;AACH;;AAED,SAAO,CAAC,CAAR;AACH,CAdM","sourcesContent":["// used in configure too, for consistency modify it there too\nexport const multiplePlacements = { enabled: 'Yes', disabled: 'No', perChoice: 'Set Per Choice' };\n\n// used to validate the config\nexport const isCorrectResponseDuplicated = (choices,alternate) => {\n if (choices.length < 1 || alternate.length < 1){\n return -1;\n }\n const stringChoices = JSON.stringify(choices.sort());\n const stringAlternate = alternate.reduce((total, current) => current.length > 0 ? [...total, JSON.stringify(current.sort())] : total, []);\n const foundIndexDuplicate = stringAlternate.findIndex(alternate => alternate.length && alternate === stringChoices);\n return foundIndexDuplicate;\n};\n\nexport const isAlternateDuplicated = (alternate) => {\n if (alternate.length <= 1){\n return -1;\n }\n const elementSet = new Set();\n const stringAlternate = alternate.reduce((total, current) => current.length > 0 ? [...total, JSON.stringify(current.sort())] : total, []);\n for (let i = 0; i < stringAlternate.length; i++) {\n if (elementSet.has(stringAlternate[i]) && stringAlternate[i]) {\n return i;\n }\n elementSet.add(stringAlternate[i]);\n }\n\n return -1;\n};\n"],"file":"utils.js"}
@@ -2,12 +2,12 @@
2
2
  "name": "@pie-element/categorize-controller",
3
3
  "private": true,
4
4
  "dependencies": {
5
- "@pie-lib/categorize": "^0.6.22",
6
- "@pie-lib/controller-utils": "^0.2.24",
7
- "@pie-lib/feedback": "^0.4.25",
5
+ "@pie-lib/categorize": "^0.8.12",
6
+ "@pie-lib/controller-utils": "^0.2.42",
7
+ "@pie-lib/feedback": "^0.4.42",
8
8
  "lodash": "^4.17.15"
9
9
  },
10
- "version": "5.1.16",
10
+ "version": "5.7.0",
11
11
  "description": "",
12
12
  "scripts": {},
13
13
  "main": "lib/index.js",