@pie-element/graphing 6.2.2-beta.5 → 6.2.2-beta.6

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.
@@ -0,0 +1,465 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.getBestAnswer = exports.getAnswerCorrected = exports.createCorrectResponseSession = exports.compareMarks = exports.comparLabelMarks = void 0;
9
+ exports.model = model;
10
+ exports.normalize = void 0;
11
+ exports.outcome = outcome;
12
+ exports.validate = void 0;
13
+
14
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
15
+
16
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
+
18
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
19
+
20
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
21
+
22
+ var _debug = _interopRequireDefault(require("debug"));
23
+
24
+ var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
25
+
26
+ var _uniqWith = _interopRequireDefault(require("lodash/uniqWith"));
27
+
28
+ var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));
29
+
30
+ var _defaults = _interopRequireDefault(require("./defaults"));
31
+
32
+ var _utils = require("./utils");
33
+
34
+ var _controllerUtils = require("@pie-lib/pie-toolbox/controller-utils");
35
+
36
+ var _excluded = ["defaultTool", "extraCSSRules", "prompt", "promptEnabled", "graph", "answers", "toolbarTools"];
37
+
38
+ 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; }
39
+
40
+ 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; }
41
+
42
+ var log = (0, _debug["default"])('@pie-element:graphing:controller');
43
+
44
+ var initializeGraphMap = function initializeGraphMap() {
45
+ return {
46
+ point: [],
47
+ segment: [],
48
+ line: [],
49
+ ray: [],
50
+ vector: [],
51
+ polygon: [],
52
+ circle: [],
53
+ sine: [],
54
+ parabola: [],
55
+ absolute: [],
56
+ exponential: []
57
+ };
58
+ };
59
+
60
+ var graphObjectsOrder = {
61
+ incorrect: 0,
62
+ correct: 1,
63
+ missing: 2
64
+ };
65
+
66
+ var compareMarks = function compareMarks(mark1, mark2) {
67
+ // marks can be compared with equalMarks[type] function only if they have the same type;
68
+ // if type is different, they are clearly not equal
69
+ return !!(mark1 && mark2 && mark1.type === mark2.type && _utils.equalMarks[mark1.type] && _utils.equalMarks[mark1.type](mark1, mark2));
70
+ };
71
+
72
+ exports.compareMarks = compareMarks;
73
+
74
+ var comparLabelMarks = function comparLabelMarks(mark1, mark2) {
75
+ return mark1.label === mark2.label ? 'correct' : 'incorrect';
76
+ };
77
+
78
+ exports.comparLabelMarks = comparLabelMarks;
79
+
80
+ var getAnswerCorrected = function getAnswerCorrected(_ref) {
81
+ var sessionAnswers = _ref.sessionAnswers,
82
+ correctAnswers = _ref.marks;
83
+ sessionAnswers = sessionAnswers || [];
84
+ correctAnswers = correctAnswers || [];
85
+ var rez = (0, _cloneDeep["default"])(sessionAnswers).reduce(function (correctedAnswer, answer) {
86
+ var answerIsCorrect = correctAnswers.find(function (mark) {
87
+ return compareMarks(answer, mark);
88
+ });
89
+ answer.correctness = answerIsCorrect ? 'correct' : 'incorrect';
90
+
91
+ if (answerIsCorrect) {
92
+ answer.correctnesslabel = comparLabelMarks(answer, answerIsCorrect);
93
+ answer.correctlabel = answerIsCorrect.label ? answerIsCorrect.label : '';
94
+ answer.label = answer.label ? answer.label : '';
95
+ }
96
+
97
+ return [].concat((0, _toConsumableArray2["default"])(correctedAnswer), [answer]);
98
+ }, []); // add missing objects from correct answer
99
+
100
+ var missingAnswers = (0, _cloneDeep["default"])(correctAnswers).reduce(function (correctedAnswer, answer) {
101
+ var answerIndex = sessionAnswers.find(function (mark) {
102
+ return compareMarks(answer, mark);
103
+ });
104
+
105
+ if (!answerIndex) {
106
+ // means that corrected answer is missing from session, so we mark it as missing object
107
+ return [].concat((0, _toConsumableArray2["default"])(correctedAnswer), [_objectSpread(_objectSpread({}, answer), {}, {
108
+ correctness: 'missing'
109
+ })]);
110
+ }
111
+
112
+ return correctedAnswer;
113
+ }, []);
114
+ return [].concat((0, _toConsumableArray2["default"])(rez), (0, _toConsumableArray2["default"])(missingAnswers));
115
+ };
116
+
117
+ exports.getAnswerCorrected = getAnswerCorrected;
118
+
119
+ var getPartialScoring = function getPartialScoring(_ref2) {
120
+ var scoringType = _ref2.scoringType,
121
+ env = _ref2.env;
122
+ var pS = scoringType; // if scoringType is undefined, partialScoring should be considered undefined (not set)
123
+ // because partialScoring.enabled is using that information
124
+ // if it has a value, we check if it is partial scoring or dichotomous
125
+
126
+ if (scoringType) {
127
+ pS = scoringType === 'partial scoring';
128
+ }
129
+
130
+ return _controllerUtils.partialScoring.enabled({
131
+ partialScoring: pS
132
+ }, env);
133
+ };
134
+
135
+ var getBestAnswer = function getBestAnswer(question, session) {
136
+ var env = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
137
+
138
+ // questionPossibleAnswers contains all possible answers (correct response and alternates);
139
+ var _ref3 = question || {},
140
+ _ref3$answers = _ref3.answers,
141
+ questionPossibleAnswers = _ref3$answers === void 0 ? {} : _ref3$answers,
142
+ scoringType = _ref3.scoringType;
143
+
144
+ var _ref4 = session || {},
145
+ answer = _ref4.answer; // filter the incomplete objects
146
+
147
+
148
+ Object.entries(questionPossibleAnswers || {}).forEach(function (_ref5) {
149
+ var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2),
150
+ key = _ref6[0],
151
+ value = _ref6[1];
152
+
153
+ return questionPossibleAnswers[key] = _objectSpread(_objectSpread({}, value), {}, {
154
+ marks: value === null || value === void 0 ? void 0 : value.marks.filter(function (mark) {
155
+ return !mark.building;
156
+ })
157
+ });
158
+ }); // initialize answer if no values
159
+
160
+ answer = answer || []; //filter the incomplete objects for student response - Fix for SC-33160
161
+
162
+ answer = answer.filter(function (mark) {
163
+ return !mark.building;
164
+ }); // initialize one possible answer if no values
165
+
166
+ if ((0, _isEmpty["default"])(questionPossibleAnswers)) {
167
+ questionPossibleAnswers = {
168
+ correctAnswer: initializeGraphMap()
169
+ };
170
+ } else {
171
+ questionPossibleAnswers = _objectSpread({
172
+ correctAnswer: questionPossibleAnswers.correctAnswer
173
+ }, (0, _utils.sortedAnswers)(questionPossibleAnswers));
174
+ }
175
+
176
+ var partialScoringEnabled = getPartialScoring({
177
+ scoringType: scoringType,
178
+ env: env
179
+ }); // student's answers without DUPLICATES
180
+
181
+ var sessionAnswers = (0, _uniqWith["default"])(answer, compareMarks); // array of possible answers entries
182
+
183
+ var possibleAnswers = Object.entries(questionPossibleAnswers);
184
+ return possibleAnswers.reduce(function (acc, entry) {
185
+ // iterating each possible answer (main + alternates)
186
+ var possibleAnswerKey = entry[0];
187
+ var possibleAnswer = entry[1] || {};
188
+ var marks = possibleAnswer.marks;
189
+
190
+ if (!marks || !marks.length) {
191
+ return acc;
192
+ } // returns array of marks, each having 'correctness' property
193
+
194
+
195
+ var correctedAnswer = getAnswerCorrected({
196
+ sessionAnswers: sessionAnswers,
197
+ marks: marks
198
+ });
199
+ var correctMarks = correctedAnswer.filter(function (answer) {
200
+ return answer.correctness === 'correct';
201
+ }); // filter out missing objects because they do not affect the calculation of the score
202
+ // only correct and incorrect are needed
203
+
204
+ var scoredCorrectedAnswer = correctedAnswer.filter(function (answer) {
205
+ return answer.correctness !== 'missing';
206
+ });
207
+ var maxScore = marks.length;
208
+ var score = correctMarks.length; // if extra placements
209
+
210
+ if (scoredCorrectedAnswer.length > maxScore) {
211
+ score -= scoredCorrectedAnswer.length - maxScore;
212
+ }
213
+
214
+ if (score < 0) {
215
+ score = 0;
216
+ }
217
+
218
+ if (score / maxScore > acc.bestScore || !acc.foundOneSolution) {
219
+ if (partialScoringEnabled) {
220
+ acc.bestScore = parseFloat((score / maxScore).toFixed(2));
221
+ } else {
222
+ acc.bestScore = Math.floor(score / maxScore);
223
+ }
224
+
225
+ acc.bestScoreAnswerKey = possibleAnswerKey;
226
+ acc.answersCorrected = correctedAnswer;
227
+ acc.foundOneSolution = true;
228
+ }
229
+
230
+ return acc;
231
+ }, {
232
+ bestScore: 0,
233
+ bestScoreAnswerKey: null,
234
+ // initially we just suppose all the answers are incorrect
235
+ answersCorrected: (0, _cloneDeep["default"])(sessionAnswers).map(function (answer) {
236
+ return _objectSpread(_objectSpread({}, answer), {}, {
237
+ correctness: 'incorrect'
238
+ });
239
+ }),
240
+ foundOneSolution: false
241
+ });
242
+ };
243
+
244
+ exports.getBestAnswer = getBestAnswer;
245
+
246
+ var normalize = function normalize(question) {
247
+ return _objectSpread(_objectSpread({}, _defaults["default"]), question);
248
+ };
249
+
250
+ exports.normalize = normalize;
251
+
252
+ function model(question, session, env) {
253
+ return new Promise(function (resolve) {
254
+ var normalizedQuestion = normalize(question); // added a sanity check for session for environments where it is not passed initially (ex. pie-website)
255
+
256
+ if (session === undefined || session === null) {
257
+ session = {};
258
+ } // ensure removing of invalid answers
259
+ // need this if undo redo was last operation
260
+
261
+
262
+ session.answer = (0, _utils.removeInvalidAnswers)(session.answer); // console.log('normalizedQuestion', normalizedQuestion);
263
+
264
+ var _ref7 = normalizedQuestion || {},
265
+ defaultTool = _ref7.defaultTool,
266
+ extraCSSRules = _ref7.extraCSSRules,
267
+ prompt = _ref7.prompt,
268
+ promptEnabled = _ref7.promptEnabled,
269
+ graph = _ref7.graph,
270
+ answers = _ref7.answers,
271
+ toolbarTools = _ref7.toolbarTools,
272
+ questionProps = (0, _objectWithoutProperties2["default"])(_ref7, _excluded);
273
+
274
+ var arrows = normalizedQuestion.arrows;
275
+
276
+ var _ref8 = env || {},
277
+ mode = _ref8.mode,
278
+ role = _ref8.role; // This is used for offering support for old models which have the property arrows: boolean
279
+ // Same thing is set in authoring : packages/graphing/configure/src/configure.jsx - componentDidMount
280
+
281
+
282
+ if (typeof arrows === 'boolean') {
283
+ if (arrows) {
284
+ arrows = {
285
+ left: true,
286
+ right: true,
287
+ up: true,
288
+ down: true
289
+ };
290
+ } else {
291
+ arrows = {
292
+ left: false,
293
+ right: false,
294
+ up: false,
295
+ down: false
296
+ };
297
+ }
298
+ } // added support for models without defaultTool defined; also used in packages/graphing/configure/src/index.js
299
+
300
+
301
+ var toolbarToolsNoLabel = (toolbarTools || []).filter(function (tool) {
302
+ return tool !== 'label';
303
+ });
304
+ var normalizedDefaultTool = defaultTool || toolbarToolsNoLabel.length && toolbarToolsNoLabel[0] || '';
305
+
306
+ var base = _objectSpread(_objectSpread({}, questionProps), {}, {
307
+ answers: answers,
308
+ arrows: arrows,
309
+ defaultTool: normalizedDefaultTool,
310
+ disabled: env.mode !== 'gather',
311
+ prompt: promptEnabled ? prompt : null,
312
+ rationale: null,
313
+ size: graph,
314
+ showKeyLegend: env.mode === 'evaluate',
315
+ showToggle: env.mode === 'evaluate' && !(0, _isEmpty["default"])(answers) && answers.correctAnswer && answers.correctAnswer.marks && !(0, _isEmpty["default"])(answers.correctAnswer.marks),
316
+ teacherInstructions: null,
317
+ toolbarTools: toolbarTools,
318
+ extraCSSRules: extraCSSRules
319
+ });
320
+
321
+ if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {
322
+ var _ref9 = normalizedQuestion || {},
323
+ rationale = _ref9.rationale,
324
+ rationaleEnabled = _ref9.rationaleEnabled,
325
+ teacherInstructions = _ref9.teacherInstructions,
326
+ teacherInstructionsEnabled = _ref9.teacherInstructionsEnabled;
327
+
328
+ base.rationale = rationaleEnabled ? rationale : null;
329
+ base.teacherInstructions = teacherInstructionsEnabled ? teacherInstructions : null;
330
+ }
331
+
332
+ if (mode === 'evaluate') {
333
+ if (!(0, _isEmpty["default"])(answers) && answers.correctAnswer && answers.correctAnswer.marks && !(0, _isEmpty["default"])(answers.correctAnswer.marks)) {
334
+ var _getBestAnswer = getBestAnswer(normalizedQuestion, session, env),
335
+ answersCorrected = _getBestAnswer.answersCorrected,
336
+ bestScoreAnswerKey = _getBestAnswer.bestScoreAnswerKey,
337
+ bestScore = _getBestAnswer.bestScore; // array of marks from session with 'correctness' property set
338
+
339
+
340
+ base.answersCorrected = answersCorrected.sort(function (a, b) {
341
+ return graphObjectsOrder[a.correctness] - graphObjectsOrder[b.correctness];
342
+ });
343
+ base.correctResponse = bestScoreAnswerKey ? (answers[bestScoreAnswerKey] || {}).marks : [];
344
+ base.showToggle = base.showToggle && bestScore !== 1;
345
+ } else {
346
+ base.answersCorrected = session && session.answer || [];
347
+ base.correctResponse = [];
348
+ }
349
+ }
350
+
351
+ log('base: ', base);
352
+ resolve(base);
353
+ });
354
+ }
355
+
356
+ function outcome(question, session) {
357
+ var env = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
358
+ return new Promise(function (resolve) {
359
+ if (!session || (0, _isEmpty["default"])(session)) {
360
+ resolve({
361
+ score: 0,
362
+ empty: true
363
+ });
364
+ }
365
+
366
+ if (env.mode !== 'evaluate' || (0, _isEmpty["default"])(question.answers) || question.answers && question.answers.correctAnswer && (0, _isEmpty["default"])(question.answers.correctAnswer.marks)) {
367
+ resolve({
368
+ score: 0
369
+ });
370
+ }
371
+
372
+ var _getBestAnswer2 = getBestAnswer(question, session, env),
373
+ bestScore = _getBestAnswer2.bestScore;
374
+
375
+ resolve({
376
+ score: bestScore
377
+ });
378
+ });
379
+ }
380
+
381
+ var createCorrectResponseSession = function createCorrectResponseSession(question, env) {
382
+ return new Promise(function (resolve) {
383
+ if (env.mode !== 'evaluate' && env.role === 'instructor') {
384
+ var _ref10 = question || {},
385
+ answers = _ref10.answers;
386
+
387
+ var marks = [];
388
+
389
+ if (answers && Object.values(answers)) {
390
+ var correctAnswer = answers.correctAnswer || Object.values(answers)[0] || {};
391
+ marks = correctAnswer.marks || [];
392
+ }
393
+
394
+ resolve({
395
+ answer: marks,
396
+ id: '1'
397
+ });
398
+ } else {
399
+ resolve(null);
400
+ }
401
+ });
402
+ }; // remove all html tags
403
+
404
+
405
+ exports.createCorrectResponseSession = createCorrectResponseSession;
406
+
407
+ var getInnerText = function getInnerText(html) {
408
+ return (html || '').replaceAll(/<[^>]*>/g, '');
409
+ }; // remove all html tags except img and iframe
410
+
411
+
412
+ var getContent = function getContent(html) {
413
+ return (html || '').replace(/(<(?!img|iframe)([^>]+)>)/gi, '');
414
+ };
415
+
416
+ var validate = function validate() {
417
+ var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
418
+ var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
419
+ var answers = model.answers,
420
+ toolbarTools = model.toolbarTools;
421
+ var errors = {};
422
+ var correctAnswerErrors = {};
423
+ var toolbarToolsNoLabel = (toolbarTools || []).filter(function (tool) {
424
+ return tool !== 'label';
425
+ });
426
+
427
+ if (!toolbarToolsNoLabel.length) {
428
+ errors.toolbarToolsError = 'There should be at least 1 tool defined.';
429
+ }
430
+
431
+ ['teacherInstructions', 'prompt', 'rationale'].forEach(function (field) {
432
+ var _config$field;
433
+
434
+ if ((_config$field = config[field]) !== null && _config$field !== void 0 && _config$field.required && !getContent(model[field])) {
435
+ errors[field] = 'This field is required.';
436
+ }
437
+ });
438
+ Object.entries(answers || {}).forEach(function (_ref11) {
439
+ var _ref12 = (0, _slicedToArray2["default"])(_ref11, 2),
440
+ key = _ref12[0],
441
+ value = _ref12[1];
442
+
443
+ if (!value.marks.length) {
444
+ correctAnswerErrors[key] = 'At least 1 graph object should be defined.';
445
+ } // check if all graph objects are correctly defined with respect to root, edge and from, to
446
+
447
+
448
+ if (value.marks.length > 0) {
449
+ value.marks.forEach(function (mark) {
450
+ if (mark.building) {
451
+ correctAnswerErrors[key] = 'At least 1 graph object is not correctly defined.';
452
+ }
453
+ });
454
+ }
455
+ });
456
+
457
+ if (!(0, _isEmpty["default"])(correctAnswerErrors)) {
458
+ errors.correctAnswerErrors = correctAnswerErrors;
459
+ }
460
+
461
+ return errors;
462
+ };
463
+
464
+ exports.validate = validate;
465
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.js"],"names":["log","initializeGraphMap","point","segment","line","ray","vector","polygon","circle","sine","parabola","absolute","exponential","graphObjectsOrder","incorrect","correct","missing","compareMarks","mark1","mark2","type","equalMarks","comparLabelMarks","label","getAnswerCorrected","sessionAnswers","correctAnswers","marks","rez","reduce","correctedAnswer","answer","answerIsCorrect","find","mark","correctness","correctnesslabel","correctlabel","missingAnswers","answerIndex","getPartialScoring","scoringType","env","pS","partialScoring","enabled","getBestAnswer","question","session","answers","questionPossibleAnswers","Object","entries","forEach","key","value","filter","building","correctAnswer","partialScoringEnabled","possibleAnswers","acc","entry","possibleAnswerKey","possibleAnswer","length","correctMarks","scoredCorrectedAnswer","maxScore","score","bestScore","foundOneSolution","parseFloat","toFixed","Math","floor","bestScoreAnswerKey","answersCorrected","map","normalize","defaults","model","Promise","resolve","normalizedQuestion","undefined","defaultTool","extraCSSRules","prompt","promptEnabled","graph","toolbarTools","questionProps","arrows","mode","role","left","right","up","down","toolbarToolsNoLabel","tool","normalizedDefaultTool","base","disabled","rationale","size","showKeyLegend","showToggle","teacherInstructions","rationaleEnabled","teacherInstructionsEnabled","sort","a","b","correctResponse","outcome","empty","createCorrectResponseSession","values","id","getInnerText","html","replaceAll","getContent","replace","validate","config","errors","correctAnswerErrors","toolbarToolsError","field","required"],"mappings":"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","sourcesContent":["import debug from 'debug';\n\nimport cloneDeep from 'lodash/cloneDeep';\nimport uniqWith from 'lodash/uniqWith';\nimport isEmpty from 'lodash/isEmpty';\nimport defaults from './defaults';\nimport { equalMarks, sortedAnswers, removeInvalidAnswers } from './utils';\n\nimport { partialScoring } from '@pie-lib/pie-toolbox/controller-utils';\n\nconst log = debug('@pie-element:graphing:controller');\n\nconst initializeGraphMap = () => ({\n point: [],\n segment: [],\n line: [],\n ray: [],\n vector: [],\n polygon: [],\n circle: [],\n sine: [],\n parabola: [],\n absolute: [],\n exponential: [],\n});\n\nconst graphObjectsOrder = {\n incorrect: 0,\n correct: 1,\n missing: 2,\n};\n\nexport const compareMarks = (mark1, mark2) => {\n // marks can be compared with equalMarks[type] function only if they have the same type;\n // if type is different, they are clearly not equal\n return !!(\n mark1 &&\n mark2 &&\n mark1.type === mark2.type &&\n equalMarks[mark1.type] &&\n equalMarks[mark1.type](mark1, mark2)\n );\n};\n\nexport const comparLabelMarks = (mark1, mark2) => {\n return mark1.label === mark2.label ? 'correct' : 'incorrect';\n};\n\nexport const getAnswerCorrected = ({ sessionAnswers, marks: correctAnswers }) => {\n sessionAnswers = sessionAnswers || [];\n correctAnswers = correctAnswers || [];\n\n const rez = cloneDeep(sessionAnswers).reduce((correctedAnswer, answer) => {\n const answerIsCorrect = correctAnswers.find((mark) => compareMarks(answer, mark));\n\n answer.correctness = answerIsCorrect ? 'correct' : 'incorrect';\n if (answerIsCorrect) {\n answer.correctnesslabel = comparLabelMarks(answer, answerIsCorrect);\n answer.correctlabel = answerIsCorrect.label ? answerIsCorrect.label : '';\n answer.label = answer.label ? answer.label : '';\n }\n return [...correctedAnswer, answer];\n }, []);\n\n // add missing objects from correct answer\n const missingAnswers = cloneDeep(correctAnswers).reduce((correctedAnswer, answer) => {\n const answerIndex = sessionAnswers.find((mark) => compareMarks(answer, mark));\n\n if (!answerIndex) {\n // means that corrected answer is missing from session, so we mark it as missing object\n return [...correctedAnswer, { ...answer, correctness: 'missing' }];\n }\n\n return correctedAnswer;\n }, []);\n\n return [...rez, ...missingAnswers];\n};\n\nconst getPartialScoring = ({ scoringType, env }) => {\n let pS = scoringType;\n\n // if scoringType is undefined, partialScoring should be considered undefined (not set)\n // because partialScoring.enabled is using that information\n // if it has a value, we check if it is partial scoring or dichotomous\n if (scoringType) {\n pS = scoringType === 'partial scoring';\n }\n\n return partialScoring.enabled({ partialScoring: pS }, env);\n};\n\nexport const getBestAnswer = (question, session, env = {}) => {\n // questionPossibleAnswers contains all possible answers (correct response and alternates);\n let { answers: questionPossibleAnswers = {}, scoringType } = question || {};\n let { answer } = session || {};\n\n // filter the incomplete objects\n Object.entries(questionPossibleAnswers || {}).forEach(\n ([key, value]) =>\n (questionPossibleAnswers[key] = { ...value, marks: value?.marks.filter((mark) => !mark.building) }),\n );\n\n // initialize answer if no values\n answer = answer || [];\n \n //filter the incomplete objects for student response - Fix for SC-33160\n answer = answer.filter((mark) => !mark.building);\n\n // initialize one possible answer if no values\n if (isEmpty(questionPossibleAnswers)) {\n questionPossibleAnswers = { correctAnswer: initializeGraphMap() };\n } else {\n questionPossibleAnswers = {\n correctAnswer: questionPossibleAnswers.correctAnswer,\n ...sortedAnswers(questionPossibleAnswers),\n };\n }\n\n const partialScoringEnabled = getPartialScoring({ scoringType, env });\n\n // student's answers without DUPLICATES\n const sessionAnswers = uniqWith(answer, compareMarks);\n // array of possible answers entries\n const possibleAnswers = Object.entries(questionPossibleAnswers);\n\n return possibleAnswers.reduce(\n (acc, entry) => {\n // iterating each possible answer (main + alternates)\n const possibleAnswerKey = entry[0];\n const possibleAnswer = entry[1] || {};\n let { marks } = possibleAnswer;\n\n if (!marks || !marks.length) {\n return acc;\n }\n\n // returns array of marks, each having 'correctness' property\n const correctedAnswer = getAnswerCorrected({ sessionAnswers, marks });\n const correctMarks = correctedAnswer.filter((answer) => answer.correctness === 'correct');\n // filter out missing objects because they do not affect the calculation of the score\n // only correct and incorrect are needed\n const scoredCorrectedAnswer = correctedAnswer.filter((answer) => answer.correctness !== 'missing');\n\n const maxScore = marks.length;\n let score = correctMarks.length;\n\n // if extra placements\n if (scoredCorrectedAnswer.length > maxScore) {\n score -= scoredCorrectedAnswer.length - maxScore;\n }\n\n if (score < 0) {\n score = 0;\n }\n\n if (score / maxScore > acc.bestScore || !acc.foundOneSolution) {\n if (partialScoringEnabled) {\n acc.bestScore = parseFloat((score / maxScore).toFixed(2));\n } else {\n acc.bestScore = Math.floor(score / maxScore);\n }\n\n acc.bestScoreAnswerKey = possibleAnswerKey;\n acc.answersCorrected = correctedAnswer;\n acc.foundOneSolution = true;\n }\n\n return acc;\n },\n {\n bestScore: 0,\n bestScoreAnswerKey: null,\n // initially we just suppose all the answers are incorrect\n answersCorrected: cloneDeep(sessionAnswers).map((answer) => ({ ...answer, correctness: 'incorrect' })),\n foundOneSolution: false,\n },\n );\n};\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\nexport function model(question, session, env) {\n return new Promise((resolve) => {\n const normalizedQuestion = normalize(question);\n\n // added a sanity check for session for environments where it is not passed initially (ex. pie-website)\n if (session === undefined || session === null) {\n session = {};\n }\n // ensure removing of invalid answers\n // need this if undo redo was last operation\n session.answer = removeInvalidAnswers(session.answer);\n // console.log('normalizedQuestion', normalizedQuestion);\n const { defaultTool, extraCSSRules, prompt, promptEnabled, graph, answers, toolbarTools, ...questionProps } =\n normalizedQuestion || {};\n let { arrows } = normalizedQuestion;\n const { mode, role } = env || {};\n\n // This is used for offering support for old models which have the property arrows: boolean\n // Same thing is set in authoring : packages/graphing/configure/src/configure.jsx - componentDidMount\n if (typeof arrows === 'boolean') {\n if (arrows) {\n arrows = {\n left: true,\n right: true,\n up: true,\n down: true,\n };\n } else {\n arrows = {\n left: false,\n right: false,\n up: false,\n down: false,\n };\n }\n }\n\n // added support for models without defaultTool defined; also used in packages/graphing/configure/src/index.js\n const toolbarToolsNoLabel = (toolbarTools || []).filter((tool) => tool !== 'label');\n const normalizedDefaultTool = defaultTool || (toolbarToolsNoLabel.length && toolbarToolsNoLabel[0]) || '';\n\n const base = {\n ...questionProps,\n answers,\n arrows,\n defaultTool: normalizedDefaultTool,\n disabled: env.mode !== 'gather',\n prompt: promptEnabled ? prompt : null,\n rationale: null,\n size: graph,\n showKeyLegend: env.mode === 'evaluate',\n showToggle:\n env.mode === 'evaluate' &&\n !isEmpty(answers) &&\n answers.correctAnswer &&\n answers.correctAnswer.marks &&\n !isEmpty(answers.correctAnswer.marks),\n teacherInstructions: null,\n toolbarTools,\n extraCSSRules,\n };\n\n if (role === 'instructor' && (mode === 'view' || mode === 'evaluate')) {\n const { rationale, rationaleEnabled, teacherInstructions, teacherInstructionsEnabled } = normalizedQuestion || {};\n\n base.rationale = rationaleEnabled ? rationale : null;\n base.teacherInstructions = teacherInstructionsEnabled ? teacherInstructions : null;\n }\n\n if (mode === 'evaluate') {\n if (\n !isEmpty(answers) &&\n answers.correctAnswer &&\n answers.correctAnswer.marks &&\n !isEmpty(answers.correctAnswer.marks)\n ) {\n const { answersCorrected, bestScoreAnswerKey, bestScore } = getBestAnswer(normalizedQuestion, session, env);\n // array of marks from session with 'correctness' property set\n base.answersCorrected = answersCorrected.sort(\n (a, b) => graphObjectsOrder[a.correctness] - graphObjectsOrder[b.correctness],\n );\n base.correctResponse = bestScoreAnswerKey ? (answers[bestScoreAnswerKey] || {}).marks : [];\n base.showToggle = base.showToggle && bestScore !== 1;\n } else {\n base.answersCorrected = (session && session.answer) || [];\n base.correctResponse = [];\n }\n }\n\n log('base: ', base);\n resolve(base);\n });\n}\n\nexport function outcome(question, session, env = {}) {\n return new Promise((resolve) => {\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n if (\n env.mode !== 'evaluate' ||\n isEmpty(question.answers) ||\n (question.answers && question.answers.correctAnswer && isEmpty(question.answers.correctAnswer.marks))\n ) {\n resolve({ score: 0 });\n }\n\n const { bestScore } = getBestAnswer(question, session, env);\n\n resolve({ score: bestScore });\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { answers } = question || {};\n let marks = [];\n\n if (answers && Object.values(answers)) {\n const correctAnswer = answers.correctAnswer || Object.values(answers)[0] || {};\n marks = correctAnswer.marks || [];\n }\n\n resolve({\n answer: marks,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img and iframe\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const { answers, toolbarTools } = model;\n const errors = {};\n const correctAnswerErrors = {};\n const toolbarToolsNoLabel = (toolbarTools || []).filter((tool) => tool !== 'label');\n\n if (!toolbarToolsNoLabel.length) {\n errors.toolbarToolsError = 'There should be at least 1 tool defined.';\n }\n\n ['teacherInstructions', 'prompt', 'rationale'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n Object.entries(answers || {}).forEach(([key, value]) => {\n if (!value.marks.length) {\n correctAnswerErrors[key] = 'At least 1 graph object should be defined.';\n }\n\n // check if all graph objects are correctly defined with respect to root, edge and from, to\n if (value.marks.length > 0) {\n value.marks.forEach((mark) => {\n if (mark.building) {\n correctAnswerErrors[key] = 'At least 1 graph object is not correctly defined.';\n }\n });\n }\n });\n\n if (!isEmpty(correctAnswerErrors)) {\n errors.correctAnswerErrors = correctAnswerErrors;\n }\n\n return errors;\n};\n"],"file":"index.js"}