@pie-element/image-cloze-association 4.9.1-next.2 → 4.9.1-next.39
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 +1 -1
- package/configure/lib/root.js +2 -10
- package/configure/lib/root.js.map +1 -1
- package/configure/src/root.jsx +18 -26
- package/controller/lib/index.js +20 -9
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js +2 -2
- package/controller/lib/utils.js.map +1 -1
- package/controller/src/__tests__/index.test.js +52 -0
- package/controller/src/index.js +17 -5
- package/controller/src/utils.js +2 -2
- package/lib/interactive-section.js +4 -1
- package/lib/interactive-section.js.map +1 -1
- package/lib/root.js +30 -18
- package/lib/root.js.map +1 -1
- package/lib/utils-correctness.js +1 -1
- package/lib/utils-correctness.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/root.test.jsx.snap +33 -44
- package/src/interactive-section.jsx +4 -1
- package/src/root.jsx +13 -4
- package/src/utils-correctness.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -129,7 +129,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
|
|
129
129
|
|
|
130
130
|
### Features
|
|
131
131
|
|
|
132
|
-
* add a different property in the config,
|
|
132
|
+
* add a different property in the config, to force a value ([300c664](https://github.com/pie-framework/pie-elements/commit/300c664618f46177137deef3bced2d096cdb8126))
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
|
package/configure/lib/root.js
CHANGED
|
@@ -113,8 +113,6 @@ var Root = /*#__PURE__*/function (_React$Component) {
|
|
|
113
113
|
Properties: panelProperties
|
|
114
114
|
}
|
|
115
115
|
})
|
|
116
|
-
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
117
|
-
className: classes.content
|
|
118
116
|
}, model && model.teacherInstructionsEnabled && /*#__PURE__*/_react["default"].createElement(_configUi.InputContainer, {
|
|
119
117
|
label: teacherInstructions.label,
|
|
120
118
|
className: classes.promptHolder
|
|
@@ -133,7 +131,7 @@ var Root = /*#__PURE__*/function (_React$Component) {
|
|
|
133
131
|
}, {
|
|
134
132
|
language: 'special'
|
|
135
133
|
}]
|
|
136
|
-
})), /*#__PURE__*/_react["default"].createElement("div", null, "Image cloze association"))
|
|
134
|
+
})), /*#__PURE__*/_react["default"].createElement("div", null, "Image cloze association"));
|
|
137
135
|
}
|
|
138
136
|
}]);
|
|
139
137
|
return Root;
|
|
@@ -143,16 +141,10 @@ exports.Root = Root;
|
|
|
143
141
|
|
|
144
142
|
var styles = function styles(theme) {
|
|
145
143
|
return {
|
|
146
|
-
base: {
|
|
147
|
-
marginTop: theme.spacing.unit * 3
|
|
148
|
-
},
|
|
149
144
|
promptHolder: {
|
|
150
145
|
width: '100%',
|
|
151
|
-
paddingTop: theme.spacing.unit * 2
|
|
152
|
-
},
|
|
153
|
-
prompt: {
|
|
154
146
|
paddingTop: theme.spacing.unit * 2,
|
|
155
|
-
|
|
147
|
+
marginBottom: theme.spacing.unit * 2
|
|
156
148
|
}
|
|
157
149
|
};
|
|
158
150
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/root.jsx"],"names":["Panel","settings","toggle","Root","teacherInstructions","props","onModelChanged","model","classes","configuration","onConfigurationChanged","imageSupport","uploadSoundSupport","maxImageWidth","maxImageHeight","settingsPanelDisabled","spellCheck","withRubric","spellCheckEnabled","panelProperties","teacherInstructionsEnabled","label","rubricEnabled","config","Properties","
|
|
1
|
+
{"version":3,"sources":["../src/root.jsx"],"names":["Panel","settings","toggle","Root","teacherInstructions","props","onModelChanged","model","classes","configuration","onConfigurationChanged","imageSupport","uploadSoundSupport","maxImageWidth","maxImageHeight","settingsPanelDisabled","spellCheck","withRubric","spellCheckEnabled","panelProperties","teacherInstructionsEnabled","label","rubricEnabled","config","Properties","promptHolder","prompt","onTeacherInstructionsChanged","language","React","Component","styles","theme","width","paddingTop","spacing","unit","marginBottom","propTypes","PropTypes","object","isRequired","func","shape","add"],"mappings":"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","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { settings, layout, InputContainer } from '@pie-lib/config-ui';\nimport EditableHtml from '@pie-lib/editable-html';\nimport { withStyles } from '@material-ui/core/styles';\n\nconst { Panel, toggle } = settings;\n\nexport class Root extends React.Component {\n onTeacherInstructionsChanged = (teacherInstructions) => {\n this.props.onModelChanged({ ...this.props.model, teacherInstructions });\n };\n\n render() {\n const { classes, model, configuration, onModelChanged, onConfigurationChanged, imageSupport, uploadSoundSupport } =\n this.props;\n const {\n maxImageWidth = {},\n maxImageHeight = {},\n settingsPanelDisabled,\n spellCheck = {},\n teacherInstructions = {},\n withRubric = {},\n } = configuration || {};\n const { spellCheckEnabled } = model || {};\n\n const panelProperties = {\n teacherInstructionsEnabled: teacherInstructions.settings && toggle(teacherInstructions.label),\n spellCheckEnabled: spellCheck.settings && toggle(spellCheck.label),\n rubricEnabled: withRubric?.settings && toggle(withRubric?.label),\n };\n\n return (\n <layout.ConfigLayout\n hideSettings={settingsPanelDisabled}\n settings={\n <Panel\n model={model}\n configuration={configuration}\n onChangeModel={(model) => onModelChanged(model)}\n onChangeConfiguration={(config) => onConfigurationChanged(config)}\n groups={{\n Properties: panelProperties,\n }}\n />\n }\n >\n {model && model.teacherInstructionsEnabled && (\n <InputContainer label={teacherInstructions.label} className={classes.promptHolder}>\n <EditableHtml\n className={classes.prompt}\n markup={model.teacherInstructions || ''}\n onChange={this.onTeacherInstructionsChanged}\n imageSupport={imageSupport}\n nonEmpty={false}\n spellCheck={spellCheckEnabled}\n maxImageWidth={maxImageWidth && maxImageWidth.teacherInstructions}\n maxImageHeight={maxImageHeight && maxImageHeight.teacherInstructions}\n uploadSoundSupport={uploadSoundSupport}\n languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}\n />\n </InputContainer>\n )}\n\n <div>Image cloze association</div>\n </layout.ConfigLayout>\n );\n }\n}\n\nconst styles = (theme) => ({\n promptHolder: {\n width: '100%',\n paddingTop: theme.spacing.unit * 2,\n marginBottom: theme.spacing.unit * 2,\n },\n});\n\nRoot.propTypes = {\n classes: PropTypes.object.isRequired,\n onModelChanged: PropTypes.func,\n onConfigurationChanged: PropTypes.func,\n model: PropTypes.object.isRequired,\n configuration: PropTypes.object.isRequired,\n imageSupport: PropTypes.shape({\n add: PropTypes.func.isRequired,\n delete: PropTypes.func.isRequired,\n }),\n uploadSoundSupport: PropTypes.shape({\n add: PropTypes.func.isRequired,\n delete: PropTypes.func.isRequired,\n }),\n};\n\nexport default withStyles(styles)(Root);\n"],"file":"root.js"}
|
package/configure/src/root.jsx
CHANGED
|
@@ -45,42 +45,34 @@ export class Root extends React.Component {
|
|
|
45
45
|
/>
|
|
46
46
|
}
|
|
47
47
|
>
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)}
|
|
48
|
+
{model && model.teacherInstructionsEnabled && (
|
|
49
|
+
<InputContainer label={teacherInstructions.label} className={classes.promptHolder}>
|
|
50
|
+
<EditableHtml
|
|
51
|
+
className={classes.prompt}
|
|
52
|
+
markup={model.teacherInstructions || ''}
|
|
53
|
+
onChange={this.onTeacherInstructionsChanged}
|
|
54
|
+
imageSupport={imageSupport}
|
|
55
|
+
nonEmpty={false}
|
|
56
|
+
spellCheck={spellCheckEnabled}
|
|
57
|
+
maxImageWidth={maxImageWidth && maxImageWidth.teacherInstructions}
|
|
58
|
+
maxImageHeight={maxImageHeight && maxImageHeight.teacherInstructions}
|
|
59
|
+
uploadSoundSupport={uploadSoundSupport}
|
|
60
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
61
|
+
/>
|
|
62
|
+
</InputContainer>
|
|
63
|
+
)}
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
</div>
|
|
65
|
+
<div>Image cloze association</div>
|
|
68
66
|
</layout.ConfigLayout>
|
|
69
67
|
);
|
|
70
68
|
}
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
const styles = (theme) => ({
|
|
74
|
-
base: {
|
|
75
|
-
marginTop: theme.spacing.unit * 3,
|
|
76
|
-
},
|
|
77
72
|
promptHolder: {
|
|
78
73
|
width: '100%',
|
|
79
74
|
paddingTop: theme.spacing.unit * 2,
|
|
80
|
-
|
|
81
|
-
prompt: {
|
|
82
|
-
paddingTop: theme.spacing.unit * 2,
|
|
83
|
-
width: '100%',
|
|
75
|
+
marginBottom: theme.spacing.unit * 2,
|
|
84
76
|
},
|
|
85
77
|
});
|
|
86
78
|
|
package/controller/lib/index.js
CHANGED
|
@@ -24,6 +24,8 @@ var _controllerUtils = require("@pie-lib/controller-utils");
|
|
|
24
24
|
|
|
25
25
|
var _utils = require("./utils");
|
|
26
26
|
|
|
27
|
+
var _lodash = require("lodash");
|
|
28
|
+
|
|
27
29
|
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; }
|
|
28
30
|
|
|
29
31
|
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; }
|
|
@@ -79,7 +81,7 @@ var isResponseCorrect = function isResponseCorrect(responses, session) {
|
|
|
79
81
|
|
|
80
82
|
if (session.answers && totalValidResponses === session.answers.length) {
|
|
81
83
|
session.answers.forEach(function (answer) {
|
|
82
|
-
if (!(responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
84
|
+
if (!(responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
83
85
|
isCorrect = false;
|
|
84
86
|
}
|
|
85
87
|
});
|
|
@@ -88,15 +90,23 @@ var isResponseCorrect = function isResponseCorrect(responses, session) {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
return isCorrect;
|
|
91
|
-
}; // This applies for
|
|
93
|
+
}; // This applies for correct responses that have empty values
|
|
92
94
|
|
|
93
95
|
|
|
94
96
|
exports.isResponseCorrect = isResponseCorrect;
|
|
95
97
|
|
|
98
|
+
var keepNonEmptyResponses = function keepNonEmptyResponses(responses) {
|
|
99
|
+
var filtered = responses.filter(function (response) {
|
|
100
|
+
return response.images && response.images.length;
|
|
101
|
+
});
|
|
102
|
+
return (0, _lodash.cloneDeep)(filtered);
|
|
103
|
+
}; // This applies for items that don't support partial scoring.
|
|
104
|
+
|
|
105
|
+
|
|
96
106
|
var isDefaultOrAltResponseCorrect = function isDefaultOrAltResponseCorrect(question, session) {
|
|
97
|
-
var
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
var altResponses = question.validation.altResponses;
|
|
108
|
+
var value = question.validation.validResponse.value;
|
|
109
|
+
value = keepNonEmptyResponses(value);
|
|
100
110
|
var isCorrect = isResponseCorrect(value, session); // Look for correct answers in alternate responses.
|
|
101
111
|
|
|
102
112
|
if (!isCorrect && altResponses && altResponses.length) {
|
|
@@ -130,8 +140,7 @@ var getDeductionPerContainer = function getDeductionPerContainer(containerIndex,
|
|
|
130
140
|
|
|
131
141
|
var getPartialScore = function getPartialScore(question, session) {
|
|
132
142
|
var validResponse = question.validation.validResponse,
|
|
133
|
-
maxResponsePerZone = question.maxResponsePerZone
|
|
134
|
-
responseContainers = question.responseContainers;
|
|
143
|
+
maxResponsePerZone = question.maxResponsePerZone;
|
|
135
144
|
var correctAnswers = 0;
|
|
136
145
|
var possibleResponses = 0;
|
|
137
146
|
|
|
@@ -139,6 +148,7 @@ var getPartialScore = function getPartialScore(question, session) {
|
|
|
139
148
|
return 0;
|
|
140
149
|
}
|
|
141
150
|
|
|
151
|
+
validResponse.value = keepNonEmptyResponses(validResponse.value);
|
|
142
152
|
validResponse.value.forEach(function (value) {
|
|
143
153
|
return possibleResponses += (value.images || []).length;
|
|
144
154
|
});
|
|
@@ -167,8 +177,9 @@ var getPartialScore = function getPartialScore(question, session) {
|
|
|
167
177
|
} // negative values will implicitly make the score equal to zero
|
|
168
178
|
|
|
169
179
|
|
|
170
|
-
correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;
|
|
171
|
-
|
|
180
|
+
correctAnswers = correctAnswers < 0 ? 0 : correctAnswers; // use length of validResponse since some containers can be left empty
|
|
181
|
+
|
|
182
|
+
var denominator = maxResponsePerZone > 1 ? possibleResponses : (validResponse.value || []).length;
|
|
172
183
|
var str = (correctAnswers / denominator).toFixed(2);
|
|
173
184
|
return parseFloat(str);
|
|
174
185
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","rationaleEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","model","session","env","questionNormalized","questionCamelized","Promise","resolve","out","disabled","mode","responseCorrect","getScore","undefined","shuffle","possibleResponses","possible_responses","role","teacherInstructions","isResponseCorrect","responses","isCorrect","totalValidResponses","forEach","value","images","length","answers","answer","containerIndex","includes","isDefaultOrAltResponseCorrect","validation","validResponse","altResponses","altResponse","getDeductionPerContainer","valid","totalStack","filter","item","incorrectStack","maxValid","ignored","slice","getPartialScore","maxResponsePerZone","responseContainers","correctAnswers","all","deductionList","id","denominator","str","toFixed","parseFloat","config","isPartialScoring","partialScoring","enabled","correct","outcome","score","empty","configCamelized","createCorrectResponseSession","valid_response","container","i","v","push"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport isEmpty from 'lodash/isEmpty';\nimport shuffle from 'lodash/shuffle';\nimport { camelizeKeys } from 'humps';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nimport { getAllUniqueCorrectness } from './utils';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({\n rationaleEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n ...question,\n});\n\nexport function model(question, session, env) {\n const questionNormalized = normalize(question);\n const questionCamelized = camelizeKeys(questionNormalized);\n\n return new Promise((resolve) => {\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n ...questionCamelized,\n responseCorrect: env.mode === 'evaluate' ? getScore(questionCamelized, session) === 1 : undefined,\n };\n\n if (questionNormalized.shuffle) {\n out.possibleResponses = shuffle(questionNormalized.possible_responses);\n }\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.teacherInstructions = questionCamelized.teacherInstructionsEnabled\n ? questionCamelized.teacherInstructions\n : null;\n } else {\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n}\n\nexport const isResponseCorrect = (responses, session) => {\n let isCorrect = true;\n let totalValidResponses = 0;\n\n if (!session || isEmpty(session)) {\n return false;\n }\n\n responses.forEach((value) => (totalValidResponses += (value.images || []).length));\n\n if (session.answers && totalValidResponses === session.answers.length) {\n session.answers.forEach((answer) => {\n if (!(responses[answer.containerIndex].images || []).includes(answer.value)) {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\n return isCorrect;\n};\n\n// This applies for items that don't support partial scoring.\nconst isDefaultOrAltResponseCorrect = (question, session) => {\n const {\n validation: {\n validResponse: { value },\n altResponses,\n },\n } = question;\n\n let isCorrect = isResponseCorrect(value, session);\n\n // Look for correct answers in alternate responses.\n if (!isCorrect && altResponses && altResponses.length) {\n altResponses.forEach((altResponse) => {\n if (isResponseCorrect(altResponse.value, session)) {\n isCorrect = true;\n }\n });\n }\n return isCorrect;\n};\n\n// Deduct only the items that exceeded the maximum valid response per container.\nconst getDeductionPerContainer = (containerIndex, answers, valid) => {\n const totalStack = answers.filter((item) => item.containerIndex === containerIndex);\n const incorrectStack = totalStack.filter((item) => !item.isCorrect);\n const maxValid = (valid.value[containerIndex].images || []).length;\n\n if (totalStack.length > maxValid) {\n const ignored = totalStack.length - maxValid;\n return incorrectStack.slice(-ignored);\n }\n return [];\n};\n\nexport const getPartialScore = (question, session) => {\n const {\n validation: { validResponse },\n maxResponsePerZone,\n responseContainers,\n } = question;\n let correctAnswers = 0;\n let possibleResponses = 0;\n\n if (!session || isEmpty(session)) {\n return 0;\n }\n\n validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));\n\n if (session.answers && session.answers.length) {\n const all = getAllUniqueCorrectness(session.answers, validResponse.value);\n correctAnswers = all.filter((item) => item.isCorrect).length;\n\n // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit\n session.answers.forEach((answer) => {\n if (maxResponsePerZone > 1) {\n const deductionList = getDeductionPerContainer(answer.containerIndex, all, validResponse);\n\n if (deductionList.length) {\n deductionList.forEach((item) => {\n if (item.id === answer.id) {\n correctAnswers -= 1;\n }\n });\n }\n }\n });\n } else {\n correctAnswers = 0;\n }\n // negative values will implicitly make the score equal to zero\n correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;\n\n const denominator = maxResponsePerZone > 1 ? possibleResponses : responseContainers.length;\n const str = (correctAnswers / denominator).toFixed(2);\n\n return parseFloat(str);\n};\n\nconst getScore = (config, session, env = {}) => {\n const isPartialScoring = partialScoring.enabled(config, env);\n const correct = isDefaultOrAltResponseCorrect(config, session);\n\n return isPartialScoring ? getPartialScore(config, session) : correct ? 1 : 0;\n};\n\nexport function outcome(config, session, env = {}) {\n return new Promise((resolve) => {\n log('outcome...');\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n const configCamelized = camelizeKeys(config);\n\n if (session.answers || []) {\n const score = getScore(configCamelized, session, env);\n resolve({ score });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const {\n validation: {\n valid_response: { value },\n },\n } = question;\n const answers = [];\n\n if (value) {\n value.forEach((container, i) => {\n (container.images || []).forEach((v) => {\n answers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n resolve({\n answers,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","rationaleEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","model","session","env","questionNormalized","questionCamelized","Promise","resolve","out","disabled","mode","responseCorrect","getScore","undefined","shuffle","possibleResponses","possible_responses","role","teacherInstructions","isResponseCorrect","responses","isCorrect","totalValidResponses","forEach","value","images","length","answers","answer","containerIndex","includes","keepNonEmptyResponses","filtered","filter","response","isDefaultOrAltResponseCorrect","altResponses","validation","validResponse","altResponse","getDeductionPerContainer","valid","totalStack","item","incorrectStack","maxValid","ignored","slice","getPartialScore","maxResponsePerZone","correctAnswers","all","deductionList","id","denominator","str","toFixed","parseFloat","config","isPartialScoring","partialScoring","enabled","correct","outcome","score","empty","configCamelized","createCorrectResponseSession","valid_response","container","i","v","push"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport isEmpty from 'lodash/isEmpty';\nimport shuffle from 'lodash/shuffle';\nimport { camelizeKeys } from 'humps';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nimport { getAllUniqueCorrectness } from './utils';\nimport { cloneDeep } from 'lodash';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({\n rationaleEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n ...question,\n});\n\nexport function model(question, session, env) {\n const questionNormalized = normalize(question);\n const questionCamelized = camelizeKeys(questionNormalized);\n\n return new Promise((resolve) => {\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n ...questionCamelized,\n responseCorrect: env.mode === 'evaluate' ? getScore(questionCamelized, session) === 1 : undefined,\n };\n\n if (questionNormalized.shuffle) {\n out.possibleResponses = shuffle(questionNormalized.possible_responses);\n }\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.teacherInstructions = questionCamelized.teacherInstructionsEnabled\n ? questionCamelized.teacherInstructions\n : null;\n } else {\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n}\n\nexport const isResponseCorrect = (responses, session) => {\n let isCorrect = true;\n let totalValidResponses = 0;\n\n if (!session || isEmpty(session)) {\n return false;\n }\n\n responses.forEach((value) => (totalValidResponses += (value.images || []).length));\n\n if (session.answers && totalValidResponses === session.answers.length) {\n session.answers.forEach((answer) => {\n if (!(responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value)) {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\n return isCorrect;\n};\n\n// This applies for correct responses that have empty values\nconst keepNonEmptyResponses = (responses) => {\n const filtered = responses.filter(response => response.images && response.images.length);\n return cloneDeep(filtered);\n};\n\n// This applies for items that don't support partial scoring.\nconst isDefaultOrAltResponseCorrect = (question, session) => {\n const {\n validation: { altResponses }\n } = question;\n let {\n validation: {\n validResponse: { value },\n }\n } = question;\n\n value = keepNonEmptyResponses(value);\n\n let isCorrect = isResponseCorrect(value, session);\n\n // Look for correct answers in alternate responses.\n if (!isCorrect && altResponses && altResponses.length) {\n altResponses.forEach((altResponse) => {\n if (isResponseCorrect(altResponse.value, session)) {\n isCorrect = true;\n }\n });\n }\n return isCorrect;\n};\n\n// Deduct only the items that exceeded the maximum valid response per container.\nconst getDeductionPerContainer = (containerIndex, answers, valid) => {\n const totalStack = answers.filter((item) => item.containerIndex === containerIndex);\n const incorrectStack = totalStack.filter((item) => !item.isCorrect);\n const maxValid = (valid.value[containerIndex].images || []).length;\n\n if (totalStack.length > maxValid) {\n const ignored = totalStack.length - maxValid;\n return incorrectStack.slice(-ignored);\n }\n return [];\n};\n\nexport const getPartialScore = (question, session) => {\n const {\n validation: { validResponse },\n maxResponsePerZone,\n } = question;\n let correctAnswers = 0;\n let possibleResponses = 0;\n\n if (!session || isEmpty(session)) {\n return 0;\n }\n validResponse.value = keepNonEmptyResponses(validResponse.value);\n\n validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));\n\n if (session.answers && session.answers.length) {\n const all = getAllUniqueCorrectness(session.answers, validResponse.value);\n correctAnswers = all.filter((item) => item.isCorrect).length;\n\n // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit\n session.answers.forEach((answer) => {\n if (maxResponsePerZone > 1) {\n const deductionList = getDeductionPerContainer(answer.containerIndex, all, validResponse);\n\n if (deductionList.length) {\n deductionList.forEach((item) => {\n if (item.id === answer.id) {\n correctAnswers -= 1;\n }\n });\n }\n }\n });\n } else {\n correctAnswers = 0;\n }\n // negative values will implicitly make the score equal to zero\n correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;\n\n // use length of validResponse since some containers can be left empty\n const denominator = maxResponsePerZone > 1 ? possibleResponses : (validResponse.value || []).length;\n const str = (correctAnswers / denominator).toFixed(2);\n\n return parseFloat(str);\n};\n\nconst getScore = (config, session, env = {}) => {\n const isPartialScoring = partialScoring.enabled(config, env);\n const correct = isDefaultOrAltResponseCorrect(config, session);\n\n return isPartialScoring ? getPartialScore(config, session) : correct ? 1 : 0;\n};\n\nexport function outcome(config, session, env = {}) {\n return new Promise((resolve) => {\n log('outcome...');\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n const configCamelized = camelizeKeys(config);\n\n if (session.answers || []) {\n const score = getScore(configCamelized, session, env);\n resolve({ score });\n }\n });\n}\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const {\n validation: {\n valid_response: { value },\n },\n } = question;\n const answers = [];\n\n if (value) {\n value.forEach((container, i) => {\n (container.images || []).forEach((v) => {\n answers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n resolve({\n answers,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n"],"file":"index.js"}
|
package/controller/lib/utils.js
CHANGED
|
@@ -16,13 +16,13 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
16
16
|
var getAllCorrectness = function getAllCorrectness(answers, responses) {
|
|
17
17
|
return answers.map(function (answer) {
|
|
18
18
|
return _objectSpread(_objectSpread({}, answer), {}, {
|
|
19
|
-
isCorrect: (responses[answer.containerIndex].images || []).includes(answer.value)
|
|
19
|
+
isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value)
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
var getValidAnswer = function getValidAnswer(answer, response) {
|
|
25
|
-
return (response[answer.containerIndex].images || []).filter(function (res) {
|
|
25
|
+
return (response[answer.containerIndex] && response[answer.containerIndex].images || []).filter(function (res) {
|
|
26
26
|
return res === answer.value;
|
|
27
27
|
});
|
|
28
28
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.js"],"names":["getAllCorrectness","answers","responses","map","answer","isCorrect","containerIndex","images","includes","value","getValidAnswer","response","filter","res","getAllUniqueCorrectness","validResponses","allCorrectness","forEach","answer1","valuesToParse","answer2","length","shift","index","finalAnswer","id","valid"],"mappings":";;;;;;;;;;;;;;;AAAA,IAAMA,iBAAiB,GAAG,SAApBA,iBAAoB,CAACC,OAAD,EAAUC,SAAV;AAAA,SACxBD,OAAO,CAACE,GAAR,CAAY,UAACC,MAAD;AAAA,2CACPA,MADO;AAEVC,MAAAA,SAAS,EAAE,CAACH,SAAS,CAACE,MAAM,CAACE,cAAR,CAAT,CAAiCC,
|
|
1
|
+
{"version":3,"sources":["../src/utils.js"],"names":["getAllCorrectness","answers","responses","map","answer","isCorrect","containerIndex","images","includes","value","getValidAnswer","response","filter","res","getAllUniqueCorrectness","validResponses","allCorrectness","forEach","answer1","valuesToParse","answer2","length","shift","index","finalAnswer","id","valid"],"mappings":";;;;;;;;;;;;;;;AAAA,IAAMA,iBAAiB,GAAG,SAApBA,iBAAoB,CAACC,OAAD,EAAUC,SAAV;AAAA,SACxBD,OAAO,CAACE,GAAR,CAAY,UAACC,MAAD;AAAA,2CACPA,MADO;AAEVC,MAAAA,SAAS,EAAE,CAACH,SAAS,CAACE,MAAM,CAACE,cAAR,CAAT,IAAoCJ,SAAS,CAACE,MAAM,CAACE,cAAR,CAAT,CAAiCC,MAArE,IAA+E,EAAhF,EAAoFC,QAApF,CAA6FJ,MAAM,CAACK,KAApG;AAFD;AAAA,GAAZ,CADwB;AAAA,CAA1B;;AAMA,IAAMC,cAAc,GAAG,SAAjBA,cAAiB,CAACN,MAAD,EAASO,QAAT;AAAA,SACrB,CAACA,QAAQ,CAACP,MAAM,CAACE,cAAR,CAAR,IAAmCK,QAAQ,CAACP,MAAM,CAACE,cAAR,CAAR,CAAgCC,MAAnE,IAA6E,EAA9E,EAAkFK,MAAlF,CAAyF,UAACC,GAAD;AAAA,WAASA,GAAG,KAAKT,MAAM,CAACK,KAAxB;AAAA,GAAzF,CADqB;AAAA,CAAvB;;AAGO,IAAMK,uBAAuB,GAAG,SAA1BA,uBAA0B,CAACb,OAAD,EAAUc,cAAV,EAA6B;AAClE,MAAIC,cAAc,GAAGhB,iBAAiB,CAACC,OAAD,EAAUc,cAAV,CAAtC;AAEAd,EAAAA,OAAO,CAACgB,OAAR,CAAgB,UAACC,OAAD,EAAa;AAC3B,QAAMC,aAAa,GAAGlB,OAAO,CAACW,MAAR,CACpB,UAACQ,OAAD;AAAA,aAAaA,OAAO,CAACX,KAAR,KAAkBS,OAAO,CAACT,KAA1B,IAAmCW,OAAO,CAACd,cAAR,KAA2BY,OAAO,CAACZ,cAAnF;AAAA,KADoB,CAAtB;;AAIA,QAAIa,aAAa,CAACE,MAAd,GAAuB,CAA3B,EAA8B;AAC5B;AACAF,MAAAA,aAAa,CAACG,KAAd,GAF4B,CAG5B;;AACAH,MAAAA,aAAa,CAACF,OAAd,CAAsB,UAACR,KAAD,EAAQc,KAAR,EAAkB;AACtCP,QAAAA,cAAc,GAAGA,cAAc,CAACb,GAAf,CAAmB,UAACqB,WAAD,EAAiB;AACnD,cAAIA,WAAW,CAACC,EAAZ,KAAmBhB,KAAK,CAACgB,EAA7B,EAAiC;AAC/B,gBAAIC,KAAK,GAAGhB,cAAc,CAACc,WAAD,EAAcT,cAAd,CAA1B;AACA,mDACKS,WADL;AAEEnB,cAAAA,SAAS,EAAEqB,KAAK,CAACL,MAAN,GAAeE,KAAK,GAAG;AAFpC;AAID;;AACD,iBAAOC,WAAP;AACD,SATgB,CAAjB;AAUD,OAXD;AAYD;AACF,GAtBD;AAuBA,SAAOR,cAAP;AACD,CA3BM","sourcesContent":["const getAllCorrectness = (answers, responses) =>\n answers.map((answer) => ({\n ...answer,\n isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value),\n }));\n\nconst getValidAnswer = (answer, response) =>\n (response[answer.containerIndex] && response[answer.containerIndex].images || []).filter((res) => res === answer.value);\n\nexport const getAllUniqueCorrectness = (answers, validResponses) => {\n let allCorrectness = getAllCorrectness(answers, validResponses);\n\n answers.forEach((answer1) => {\n const valuesToParse = answers.filter(\n (answer2) => answer2.value === answer1.value && answer2.containerIndex === answer1.containerIndex,\n );\n\n if (valuesToParse.length > 1) {\n // point only to duplicates but first\n valuesToParse.shift();\n // mark duplicates as incorrect\n valuesToParse.forEach((value, index) => {\n allCorrectness = allCorrectness.map((finalAnswer) => {\n if (finalAnswer.id === value.id) {\n let valid = getValidAnswer(finalAnswer, validResponses);\n return {\n ...finalAnswer,\n isCorrect: valid.length > index + 1,\n };\n }\n return finalAnswer;\n });\n });\n }\n });\n return allCorrectness;\n};\n"],"file":"utils.js"}
|
|
@@ -163,6 +163,58 @@ describe('controller', () => {
|
|
|
163
163
|
expect(result.score).toEqual(1);
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
+
it('returns correct score for valid response with empty response containers and partialScoring: false', async () => {
|
|
167
|
+
const result = await outcome({
|
|
168
|
+
...question,
|
|
169
|
+
validation: {
|
|
170
|
+
valid_response: {
|
|
171
|
+
score: 1,
|
|
172
|
+
value: [
|
|
173
|
+
{
|
|
174
|
+
images: [rhomb, square],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
images: [],
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
}, {
|
|
183
|
+
answers: [
|
|
184
|
+
{ value: rhomb, containerIndex: 0 },
|
|
185
|
+
{ value: square, containerIndex: 0 },
|
|
186
|
+
],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(result.score).toEqual(1);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('returns correct score for valid response with empty response containers and partialScoring: true', async () => {
|
|
193
|
+
const result = await outcome({
|
|
194
|
+
...question,
|
|
195
|
+
partialScoring: true,
|
|
196
|
+
validation: {
|
|
197
|
+
valid_response: {
|
|
198
|
+
score: 1,
|
|
199
|
+
value: [
|
|
200
|
+
{
|
|
201
|
+
images: [rhomb, square],
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
images: [],
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
}, {
|
|
210
|
+
answers: [
|
|
211
|
+
{ value: rhomb, containerIndex: 0 },
|
|
212
|
+
],
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(result.score).toEqual(0.5);
|
|
216
|
+
});
|
|
217
|
+
|
|
166
218
|
describe('returns score 0 for wrong validation format', () => {
|
|
167
219
|
it('returns 0 for old value format', async () => {
|
|
168
220
|
const result = await outcome(
|
package/controller/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { camelizeKeys } from 'humps';
|
|
|
5
5
|
import { partialScoring } from '@pie-lib/controller-utils';
|
|
6
6
|
|
|
7
7
|
import { getAllUniqueCorrectness } from './utils';
|
|
8
|
+
import { cloneDeep } from 'lodash';
|
|
8
9
|
|
|
9
10
|
const log = debug('pie-elements:image-cloze-association:controller');
|
|
10
11
|
|
|
@@ -55,7 +56,7 @@ export const isResponseCorrect = (responses, session) => {
|
|
|
55
56
|
|
|
56
57
|
if (session.answers && totalValidResponses === session.answers.length) {
|
|
57
58
|
session.answers.forEach((answer) => {
|
|
58
|
-
if (!(responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
59
|
+
if (!(responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value)) {
|
|
59
60
|
isCorrect = false;
|
|
60
61
|
}
|
|
61
62
|
});
|
|
@@ -65,15 +66,25 @@ export const isResponseCorrect = (responses, session) => {
|
|
|
65
66
|
return isCorrect;
|
|
66
67
|
};
|
|
67
68
|
|
|
69
|
+
// This applies for correct responses that have empty values
|
|
70
|
+
const keepNonEmptyResponses = (responses) => {
|
|
71
|
+
const filtered = responses.filter(response => response.images && response.images.length);
|
|
72
|
+
return cloneDeep(filtered);
|
|
73
|
+
};
|
|
74
|
+
|
|
68
75
|
// This applies for items that don't support partial scoring.
|
|
69
76
|
const isDefaultOrAltResponseCorrect = (question, session) => {
|
|
70
77
|
const {
|
|
78
|
+
validation: { altResponses }
|
|
79
|
+
} = question;
|
|
80
|
+
let {
|
|
71
81
|
validation: {
|
|
72
82
|
validResponse: { value },
|
|
73
|
-
|
|
74
|
-
},
|
|
83
|
+
}
|
|
75
84
|
} = question;
|
|
76
85
|
|
|
86
|
+
value = keepNonEmptyResponses(value);
|
|
87
|
+
|
|
77
88
|
let isCorrect = isResponseCorrect(value, session);
|
|
78
89
|
|
|
79
90
|
// Look for correct answers in alternate responses.
|
|
@@ -104,7 +115,6 @@ export const getPartialScore = (question, session) => {
|
|
|
104
115
|
const {
|
|
105
116
|
validation: { validResponse },
|
|
106
117
|
maxResponsePerZone,
|
|
107
|
-
responseContainers,
|
|
108
118
|
} = question;
|
|
109
119
|
let correctAnswers = 0;
|
|
110
120
|
let possibleResponses = 0;
|
|
@@ -112,6 +122,7 @@ export const getPartialScore = (question, session) => {
|
|
|
112
122
|
if (!session || isEmpty(session)) {
|
|
113
123
|
return 0;
|
|
114
124
|
}
|
|
125
|
+
validResponse.value = keepNonEmptyResponses(validResponse.value);
|
|
115
126
|
|
|
116
127
|
validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));
|
|
117
128
|
|
|
@@ -139,7 +150,8 @@ export const getPartialScore = (question, session) => {
|
|
|
139
150
|
// negative values will implicitly make the score equal to zero
|
|
140
151
|
correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;
|
|
141
152
|
|
|
142
|
-
|
|
153
|
+
// use length of validResponse since some containers can be left empty
|
|
154
|
+
const denominator = maxResponsePerZone > 1 ? possibleResponses : (validResponse.value || []).length;
|
|
143
155
|
const str = (correctAnswers / denominator).toFixed(2);
|
|
144
156
|
|
|
145
157
|
return parseFloat(str);
|
package/controller/src/utils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const getAllCorrectness = (answers, responses) =>
|
|
2
2
|
answers.map((answer) => ({
|
|
3
3
|
...answer,
|
|
4
|
-
isCorrect: (responses[answer.containerIndex].images || []).includes(answer.value),
|
|
4
|
+
isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value),
|
|
5
5
|
}));
|
|
6
6
|
|
|
7
7
|
const getValidAnswer = (answer, response) =>
|
|
8
|
-
(response[answer.containerIndex].images || []).filter((res) => res === answer.value);
|
|
8
|
+
(response[answer.containerIndex] && response[answer.containerIndex].images || []).filter((res) => res === answer.value);
|
|
9
9
|
|
|
10
10
|
export const getAllUniqueCorrectness = (answers, validResponses) => {
|
|
11
11
|
let allCorrectness = getAllCorrectness(answers, validResponses);
|
|
@@ -99,15 +99,18 @@ InteractiveSection.defaultProps = {
|
|
|
99
99
|
responseCorrect: undefined
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
-
var styles = function styles() {
|
|
102
|
+
var styles = function styles(theme) {
|
|
103
103
|
return {
|
|
104
104
|
interactiveDefault: {
|
|
105
|
+
marginTop: theme.spacing.unit * 2,
|
|
105
106
|
border: "1px solid ".concat(_renderUi.color.disabled())
|
|
106
107
|
},
|
|
107
108
|
interactiveCorrect: {
|
|
109
|
+
marginTop: theme.spacing.unit * 2,
|
|
108
110
|
border: "2px solid ".concat(_renderUi.color.correct())
|
|
109
111
|
},
|
|
110
112
|
interactiveIncorrect: {
|
|
113
|
+
marginTop: theme.spacing.unit * 2,
|
|
111
114
|
border: "2px solid ".concat(_renderUi.color.incorrect())
|
|
112
115
|
}
|
|
113
116
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/interactive-section.jsx"],"names":["InteractiveSection","props","classes","responseCorrect","styleProp","undefined","children","classname","getClassname","evaluationStyle","display","margin","marginTop","React","Component","propTypes","PropTypes","object","oneOfType","element","array","isRequired","bool","number","defaultProps","styles","interactiveDefault","border","color","disabled","interactiveCorrect","correct","interactiveIncorrect","incorrect"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AAEA;;;;;;IAEMA,kB;;;;;;;;;;;;WACJ,wBAAe;AACb,wBAAqC,KAAKC,KAA1C;AAAA,UAAQC,OAAR,eAAQA,OAAR;AAAA,UAAiBC,eAAjB,eAAiBA,eAAjB;AACA,UAAIC,SAAJ;;AAEA,cAAQD,eAAR;AACE,aAAKE,SAAL;AACED,UAAAA,SAAS,GAAG,oBAAZ;AACA;;AACF,aAAK,IAAL;AACEA,UAAAA,SAAS,GAAG,oBAAZ;AACA;;AACF;AACEA,UAAAA,SAAS,GAAG,sBAAZ;AACA;AATJ;;AAWA,aAAOF,OAAO,CAACE,SAAD,CAAd;AACD;;;WAED,kBAAS;AACP,yBAAsC,KAAKH,KAA3C;AAAA,UAAQK,QAAR,gBAAQA,QAAR;AAAA,UAAkBH,eAAlB,gBAAkBA,eAAlB;AACA,UAAMI,SAAS,GAAG,KAAKC,YAAL,EAAlB;AACA,UAAMC,eAAe,GAAG;AACtBC,QAAAA,OAAO,EAAE,MADa;AAEtBC,QAAAA,MAAM,EAAE,QAFc;AAGtBC,QAAAA,SAAS,EAAE,CAAC;AAHU,OAAxB;AAMA,0BACE;AAAK,QAAA,SAAS,EAAEL;AAAhB,sBACE,gCAAC,0BAAD;AAAgB,QAAA,cAAc,EAAEE,eAAhC;AAAiD,QAAA,MAAM,MAAvD;AAAwD,QAAA,SAAS,EAAEN;AAAnE,QADF,EAEGG,QAFH,CADF;AAMD;;;EAlC8BO,kBAAMC,S;;AAqCvCd,kBAAkB,CAACe,SAAnB,GAA+B;AAC7Bb,EAAAA,OAAO,EAAEc,sBAAUC,MADU;AAE7BX,EAAAA,QAAQ,EAAEU,sBAAUE,SAAV,CAAoB,CAACF,sBAAUG,OAAX,EAAoBH,sBAAUI,KAA9B,CAApB,EAA0DC,UAFvC;AAG7BlB,EAAAA,eAAe,EAAEa,sBAAUE,SAAV,CAAoB,CAACF,sBAAUM,IAAX,EAAiBN,sBAAUO,MAA3B,CAApB;AAHY,CAA/B;AAMAvB,kBAAkB,CAACwB,YAAnB,GAAkC;AAChCtB,EAAAA,OAAO,EAAE,EADuB;AAEhCC,EAAAA,eAAe,EAAEE;AAFe,CAAlC;;AAKA,IAAMoB,MAAM,GAAG,SAATA,MAAS;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/interactive-section.jsx"],"names":["InteractiveSection","props","classes","responseCorrect","styleProp","undefined","children","classname","getClassname","evaluationStyle","display","margin","marginTop","React","Component","propTypes","PropTypes","object","oneOfType","element","array","isRequired","bool","number","defaultProps","styles","theme","interactiveDefault","spacing","unit","border","color","disabled","interactiveCorrect","correct","interactiveIncorrect","incorrect"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AAEA;;;;;;IAEMA,kB;;;;;;;;;;;;WACJ,wBAAe;AACb,wBAAqC,KAAKC,KAA1C;AAAA,UAAQC,OAAR,eAAQA,OAAR;AAAA,UAAiBC,eAAjB,eAAiBA,eAAjB;AACA,UAAIC,SAAJ;;AAEA,cAAQD,eAAR;AACE,aAAKE,SAAL;AACED,UAAAA,SAAS,GAAG,oBAAZ;AACA;;AACF,aAAK,IAAL;AACEA,UAAAA,SAAS,GAAG,oBAAZ;AACA;;AACF;AACEA,UAAAA,SAAS,GAAG,sBAAZ;AACA;AATJ;;AAWA,aAAOF,OAAO,CAACE,SAAD,CAAd;AACD;;;WAED,kBAAS;AACP,yBAAsC,KAAKH,KAA3C;AAAA,UAAQK,QAAR,gBAAQA,QAAR;AAAA,UAAkBH,eAAlB,gBAAkBA,eAAlB;AACA,UAAMI,SAAS,GAAG,KAAKC,YAAL,EAAlB;AACA,UAAMC,eAAe,GAAG;AACtBC,QAAAA,OAAO,EAAE,MADa;AAEtBC,QAAAA,MAAM,EAAE,QAFc;AAGtBC,QAAAA,SAAS,EAAE,CAAC;AAHU,OAAxB;AAMA,0BACE;AAAK,QAAA,SAAS,EAAEL;AAAhB,sBACE,gCAAC,0BAAD;AAAgB,QAAA,cAAc,EAAEE,eAAhC;AAAiD,QAAA,MAAM,MAAvD;AAAwD,QAAA,SAAS,EAAEN;AAAnE,QADF,EAEGG,QAFH,CADF;AAMD;;;EAlC8BO,kBAAMC,S;;AAqCvCd,kBAAkB,CAACe,SAAnB,GAA+B;AAC7Bb,EAAAA,OAAO,EAAEc,sBAAUC,MADU;AAE7BX,EAAAA,QAAQ,EAAEU,sBAAUE,SAAV,CAAoB,CAACF,sBAAUG,OAAX,EAAoBH,sBAAUI,KAA9B,CAApB,EAA0DC,UAFvC;AAG7BlB,EAAAA,eAAe,EAAEa,sBAAUE,SAAV,CAAoB,CAACF,sBAAUM,IAAX,EAAiBN,sBAAUO,MAA3B,CAApB;AAHY,CAA/B;AAMAvB,kBAAkB,CAACwB,YAAnB,GAAkC;AAChCtB,EAAAA,OAAO,EAAE,EADuB;AAEhCC,EAAAA,eAAe,EAAEE;AAFe,CAAlC;;AAKA,IAAMoB,MAAM,GAAG,SAATA,MAAS,CAACC,KAAD;AAAA,SAAY;AACzBC,IAAAA,kBAAkB,EAAE;AAClBf,MAAAA,SAAS,EAAEc,KAAK,CAACE,OAAN,CAAcC,IAAd,GAAqB,CADd;AAElBC,MAAAA,MAAM,sBAAeC,gBAAMC,QAAN,EAAf;AAFY,KADK;AAKzBC,IAAAA,kBAAkB,EAAE;AAClBrB,MAAAA,SAAS,EAAEc,KAAK,CAACE,OAAN,CAAcC,IAAd,GAAqB,CADd;AAElBC,MAAAA,MAAM,sBAAeC,gBAAMG,OAAN,EAAf;AAFY,KALK;AASzBC,IAAAA,oBAAoB,EAAE;AACpBvB,MAAAA,SAAS,EAAEc,KAAK,CAACE,OAAN,CAAcC,IAAd,GAAqB,CADZ;AAEpBC,MAAAA,MAAM,sBAAeC,gBAAMK,SAAN,EAAf;AAFc;AATG,GAAZ;AAAA,CAAf;;eAee,sBAAWX,MAAX,EAAmBzB,kBAAnB,C","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { withStyles } from '@material-ui/core';\nimport { color } from '@pie-lib/render-ui';\n\nimport EvaluationIcon from './evaluation-icon';\n\nclass InteractiveSection extends React.Component {\n getClassname() {\n const { classes, responseCorrect } = this.props;\n let styleProp;\n\n switch (responseCorrect) {\n case undefined:\n styleProp = 'interactiveDefault';\n break;\n case true:\n styleProp = 'interactiveCorrect';\n break;\n default:\n styleProp = 'interactiveIncorrect';\n break;\n }\n return classes[styleProp];\n }\n\n render() {\n const { children, responseCorrect } = this.props;\n const classname = this.getClassname();\n const evaluationStyle = {\n display: 'flex',\n margin: '0 auto',\n marginTop: -14,\n };\n\n return (\n <div className={classname}>\n <EvaluationIcon containerStyle={evaluationStyle} filled isCorrect={responseCorrect} />\n {children}\n </div>\n );\n }\n}\n\nInteractiveSection.propTypes = {\n classes: PropTypes.object,\n children: PropTypes.oneOfType([PropTypes.element, PropTypes.array]).isRequired,\n responseCorrect: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),\n};\n\nInteractiveSection.defaultProps = {\n classes: {},\n responseCorrect: undefined,\n};\n\nconst styles = (theme) => ({\n interactiveDefault: {\n marginTop: theme.spacing.unit * 2,\n border: `1px solid ${color.disabled()}`,\n },\n interactiveCorrect: {\n marginTop: theme.spacing.unit * 2,\n border: `2px solid ${color.correct()}`,\n },\n interactiveIncorrect: {\n marginTop: theme.spacing.unit * 2,\n border: `2px solid ${color.incorrect()}`,\n },\n});\n\nexport default withStyles(styles)(InteractiveSection);\n"],"file":"interactive-section.js"}
|
package/lib/root.js
CHANGED
|
@@ -63,6 +63,14 @@ var generateId = function generateId() {
|
|
|
63
63
|
return Math.random().toString(36).substring(2) + new Date().getTime().toString(36);
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
var styles = function styles(theme) {
|
|
67
|
+
return {
|
|
68
|
+
teacherInstructions: {
|
|
69
|
+
marginBottom: theme.spacing.unit * 2
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
66
74
|
var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
67
75
|
(0, _inherits2["default"])(ImageClozeAssociationComponent, _React$Component);
|
|
68
76
|
|
|
@@ -254,17 +262,19 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
254
262
|
(0, _createClass2["default"])(ImageClozeAssociationComponent, [{
|
|
255
263
|
key: "render",
|
|
256
264
|
value: function render() {
|
|
257
|
-
var _this$
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
var _this$props3 = this.props,
|
|
266
|
+
classes = _this$props3.classes,
|
|
267
|
+
_this$props3$model = _this$props3.model,
|
|
268
|
+
disabled = _this$props3$model.disabled,
|
|
269
|
+
duplicateResponses = _this$props3$model.duplicateResponses,
|
|
270
|
+
image = _this$props3$model.image,
|
|
271
|
+
stimulus = _this$props3$model.stimulus,
|
|
272
|
+
responseCorrect = _this$props3$model.responseCorrect,
|
|
273
|
+
validation = _this$props3$model.validation,
|
|
274
|
+
teacherInstructions = _this$props3$model.teacherInstructions,
|
|
275
|
+
prompt = _this$props3$model.prompt,
|
|
276
|
+
showDashedBorder = _this$props3$model.showDashedBorder,
|
|
277
|
+
mode = _this$props3$model.mode;
|
|
268
278
|
var _this$state3 = this.state,
|
|
269
279
|
answers = _this$state3.answers,
|
|
270
280
|
draggingElement = _this$state3.draggingElement,
|
|
@@ -299,17 +309,18 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
299
309
|
answersToShow = [].concat((0, _toConsumableArray2["default"])(answersToShow), (0, _toConsumableArray2["default"])((0, _utilsCorrectness.getUnansweredAnswers)(answersToShow, validation)));
|
|
300
310
|
}
|
|
301
311
|
|
|
302
|
-
return /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement(_renderUi.
|
|
303
|
-
className:
|
|
304
|
-
prompt: prompt
|
|
305
|
-
}), teacherInstructions && /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
|
|
312
|
+
return /*#__PURE__*/_react["default"].createElement("div", null, teacherInstructions && /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
|
|
313
|
+
className: classes.teacherInstructions,
|
|
306
314
|
labels: {
|
|
307
315
|
hidden: 'Show Teacher Instructions',
|
|
308
316
|
visible: 'Hide Teacher Instructions'
|
|
309
317
|
}
|
|
310
318
|
}, /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
|
|
311
319
|
prompt: teacherInstructions
|
|
312
|
-
})), /*#__PURE__*/_react["default"].createElement(
|
|
320
|
+
})), /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
|
|
321
|
+
className: "prompt",
|
|
322
|
+
prompt: prompt
|
|
323
|
+
}), /*#__PURE__*/_react["default"].createElement(_Typography["default"], null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
313
324
|
dangerouslySetInnerHTML: {
|
|
314
325
|
__html: stimulus
|
|
315
326
|
}
|
|
@@ -317,7 +328,7 @@ var ImageClozeAssociationComponent = /*#__PURE__*/function (_React$Component) {
|
|
|
317
328
|
show: showToggle,
|
|
318
329
|
toggled: showCorrect,
|
|
319
330
|
onToggle: this.toggleCorrect
|
|
320
|
-
}),
|
|
331
|
+
}), showCorrect && showToggle ? /*#__PURE__*/_react["default"].createElement(_interactiveSection["default"], {
|
|
321
332
|
responseCorrect: true
|
|
322
333
|
}, /*#__PURE__*/_react["default"].createElement(_imageContainer["default"], {
|
|
323
334
|
canDrag: false,
|
|
@@ -410,8 +421,9 @@ ImageClozeAssociationComponent.propTypes = {
|
|
|
410
421
|
ImageClozeAssociationComponent.defaultProps = {
|
|
411
422
|
classes: {}
|
|
412
423
|
};
|
|
424
|
+
var StyledComponent = (0, _styles.withStyles)(styles)(ImageClozeAssociationComponent);
|
|
413
425
|
|
|
414
|
-
var _default = (0, _drag.withDragContext)(
|
|
426
|
+
var _default = (0, _drag.withDragContext)(StyledComponent);
|
|
415
427
|
|
|
416
428
|
exports["default"] = _default;
|
|
417
429
|
//# sourceMappingURL=root.js.map
|
package/lib/root.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/root.jsx"],"names":["generateId","Math","random","toString","substring","Date","getTime","ImageClozeAssociationComponent","props","draggingElement","setState","id","value","answer","responseContainerIndex","duplicateResponses","model","updateAnswer","state","answers","possibleResponses","maxResponsePerZone","answersToStore","filter","a","containerIndex","length","answersInThisContainer","answersInOtherContainers","b","shiftedItem","shift","maxResponsePerZoneWarning","push","_","max","map","c","parseInt","isNaN","response","shouldNotPushInPossibleResponses","undefined","showCorrect","responseContainers","session","possibleResponsesWithIds","item","index","groupBy","grp","slice","flatMap","possibleResponsesFiltered","find","disabled","image","stimulus","responseCorrect","validation","teacherInstructions","prompt","showDashedBorder","mode","isEvaluateMode","showToggle","validResponse","correctAnswers","forEach","container","i","images","v","warningMessage","answersToShow","hidden","visible","__html","toggleCorrect","handleOnAnswerSelect","beginDrag","handleOnDragEnd","handleOnAnswerRemove","React","Component","WarningInfo","warning","margin","backgroundColor","padding","display","alignItems","width","height","message","paddingLeft","userSelect","classes","propTypes","PropTypes","string","object","isRequired","func","defaultProps"],"mappings":"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","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport Typography from '@material-ui/core/Typography';\nimport { withDragContext } from '@pie-lib/drag';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\nimport { ShowRationale } from '@pie-lib/icons';\nimport { Collapsible, PreviewPrompt } from '@pie-lib/render-ui';\nimport { withStyles } from '@material-ui/core/styles';\nimport CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';\n\nimport Image from './image-container';\nimport InteractiveSection from './interactive-section';\nimport PossibleResponses from './possible-responses';\nimport { getUnansweredAnswers, getAnswersCorrectness } from './utils-correctness';\nimport _ from 'lodash';\n\nconst generateId = () => Math.random().toString(36).substring(2) + new Date().getTime().toString(36);\n\nclass ImageClozeAssociationComponent extends React.Component {\n constructor(props) {\n super(props);\n const {\n model: { possibleResponses, responseContainers, duplicateResponses, maxResponsePerZone },\n session,\n } = props;\n let { answers } = session || {};\n // set id for each possible response\n const possibleResponsesWithIds = (possibleResponses || []).map((item, index) => ({\n value: item,\n id: `${index}`,\n }));\n\n answers = _(answers || [])\n .groupBy('containerIndex')\n // keep only last maxResponsePerZone answers for each zone\n .map((grp) => grp.slice(-(maxResponsePerZone || 1)))\n .flatMap()\n // set id for each answer\n .map((answer, index) => ({ ...answer, id: `${index}` }))\n // return only answer which have a valid container index\n .filter((answer) => answer.containerIndex < responseContainers.length)\n .value();\n\n const possibleResponsesFiltered = possibleResponsesWithIds.filter(\n (response) => !answers.find((answer) => answer.value === response.value),\n );\n this.state = {\n answers: answers || [],\n draggingElement: { id: '', value: '' },\n possibleResponses: duplicateResponses ? possibleResponsesWithIds : possibleResponsesFiltered,\n // set id for each response containers\n responseContainers: responseContainers.map((item, index) => ({\n index,\n ...item,\n id: `${index}`,\n })),\n maxResponsePerZone: maxResponsePerZone || 1,\n showCorrect: false,\n };\n }\n\n beginDrag = (draggingElement) => {\n this.setState({\n draggingElement,\n });\n };\n\n handleOnDragEnd = () => {\n this.setState({\n draggingElement: { id: '', value: '' },\n });\n };\n\n handleOnAnswerSelect = (answer, responseContainerIndex) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses, maxResponsePerZone } = this.state;\n let answersToStore;\n\n if (maxResponsePerZone === answers.filter((a) => a.containerIndex === responseContainerIndex).length) {\n const answersInThisContainer = answers.filter((a) => a.containerIndex === responseContainerIndex);\n const answersInOtherContainers = answers.filter((b) => b.containerIndex !== responseContainerIndex);\n\n const shiftedItem = answersInThisContainer[0];\n if (maxResponsePerZone === 1) {\n answersInThisContainer.shift(); // FIFO\n } else {\n this.setState({ maxResponsePerZoneWarning: true });\n return;\n }\n\n // if duplicates are not allowed, make sure to put the shifted value back in possible responses\n if (!duplicateResponses) {\n possibleResponses.push({\n ...shiftedItem,\n containerIndex: '',\n id: `${_.max(possibleResponses.map((c) => parseInt(c.id)).filter((id) => !isNaN(id))) + 1}`,\n });\n }\n\n // answers will be:\n // + shifted answers for the current container\n // + if duplicatesAllowed, all the other answers from other containers\n // else: all the answers from other containers that are not having the same value\n // + new answer\n answersToStore = [\n ...answersInThisContainer, // shifted\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answersInOtherContainers.filter((a) => (duplicateResponses ? true : a.value !== answer.value)), // un-shifted\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n } else {\n // answers will be:\n // + if duplicatesAllowed, all the other answers, except the one that was dragged\n // else: all the answers that are not having the same value\n // + new answer\n answersToStore = [\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answers.filter((a) => (duplicateResponses ? a.id !== answer.id : a.value !== answer.value)),\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n }\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n possibleResponses:\n // for single response per container remove answer from possible responses\n duplicateResponses\n ? possibleResponses\n : possibleResponses.filter((response) => response.value !== answer.value),\n });\n updateAnswer(answersToStore);\n };\n\n handleOnAnswerRemove = (answer) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses } = this.state;\n const answersToStore = answers.filter((a) => a.id !== answer.id);\n const shouldNotPushInPossibleResponses = answer.containerIndex === undefined; // don't duplicate possible responses\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n // push back into possible responses the removed answer if responses cannot be duplicated\n possibleResponses:\n duplicateResponses || shouldNotPushInPossibleResponses\n ? possibleResponses\n : [\n ...possibleResponses,\n {\n ...answer,\n containerIndex: undefined,\n },\n ],\n });\n updateAnswer(answersToStore);\n };\n\n toggleCorrect = (showCorrect) => this.setState({ showCorrect });\n\n render() {\n const {\n model: {\n disabled,\n duplicateResponses,\n image,\n stimulus,\n responseCorrect,\n validation,\n teacherInstructions,\n prompt,\n showDashedBorder,\n mode,\n },\n } = this.props;\n const {\n answers,\n draggingElement,\n possibleResponses,\n responseContainers,\n maxResponsePerZone,\n maxResponsePerZoneWarning,\n showCorrect,\n } = this.state;\n const isEvaluateMode = mode === 'evaluate';\n const showToggle = isEvaluateMode && !responseCorrect;\n\n const { validResponse } = validation || {};\n const correctAnswers = [];\n\n if (validResponse) {\n (validResponse.value || []).forEach((container, i) => {\n (container.images || []).forEach((v) => {\n correctAnswers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n const warningMessage =\n `You’ve reached the limit of ${maxResponsePerZone} responses per area.` +\n 'To add another response, one must first be removed.';\n\n let answersToShow =\n responseCorrect !== undefined ? getAnswersCorrectness(answers, validation, duplicateResponses) : answers;\n\n if (responseCorrect === false && maxResponsePerZone === 1) {\n answersToShow = [...answersToShow, ...getUnansweredAnswers(answersToShow, validation)];\n }\n\n return (\n <div>\n <PreviewPrompt className=\"prompt\" prompt={prompt} />\n\n {teacherInstructions && (\n <Collapsible\n labels={{\n hidden: 'Show Teacher Instructions',\n visible: 'Hide Teacher Instructions',\n }}\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </Collapsible>\n )}\n\n <Typography>\n <span dangerouslySetInnerHTML={{ __html: stimulus }} />\n </Typography>\n\n <CorrectAnswerToggle show={showToggle} toggled={showCorrect} onToggle={this.toggleCorrect} />\n <br />\n\n {showCorrect && showToggle ? (\n <InteractiveSection responseCorrect={true}>\n <Image\n canDrag={false}\n answers={correctAnswers}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n />\n </InteractiveSection>\n ) : (\n <InteractiveSection responseCorrect={responseCorrect}>\n <Image\n canDrag={!disabled}\n answers={answersToShow}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n />\n\n {maxResponsePerZoneWarning && <WarningInfo message={warningMessage} />}\n\n <PossibleResponses\n canDrag={!disabled}\n data={possibleResponses}\n onAnswerRemove={this.handleOnAnswerRemove}\n onDragBegin={this.beginDrag}\n onDragEnd={this.handleOnDragEnd}\n />\n </InteractiveSection>\n )}\n </div>\n );\n }\n}\n\nconst WarningInfo = withStyles({\n warning: {\n margin: '0 16px',\n backgroundColor: '#dddddd',\n padding: '10px',\n display: 'flex',\n alignItems: 'center',\n width: 'fit-content',\n '& svg': {\n height: '30px',\n },\n '& h1': {\n padding: '0px',\n margin: '0px',\n },\n },\n message: {\n paddingLeft: '5px',\n userSelect: 'none',\n },\n})(({ classes, message }) => (\n <TransitionGroup>\n <CSSTransition classNames={'fb'} key=\"fb\" timeout={300}>\n <div key=\"panel\" className={classes.warning}>\n <ShowRationale iconSet=\"emoji\" shape=\"square\" />\n <span className={classes.message} dangerouslySetInnerHTML={{ __html: message }} />\n </div>\n </CSSTransition>\n </TransitionGroup>\n));\n\nWarningInfo.propTypes = {\n message: PropTypes.string,\n classes: PropTypes.object.isRequired,\n};\n\nImageClozeAssociationComponent.propTypes = {\n classes: PropTypes.object,\n model: PropTypes.object.isRequired,\n session: PropTypes.object,\n updateAnswer: PropTypes.func.isRequired,\n};\n\nImageClozeAssociationComponent.defaultProps = {\n classes: {},\n};\n\nexport default withDragContext(ImageClozeAssociationComponent);\n"],"file":"root.js"}
|
|
1
|
+
{"version":3,"sources":["../src/root.jsx"],"names":["generateId","Math","random","toString","substring","Date","getTime","styles","theme","teacherInstructions","marginBottom","spacing","unit","ImageClozeAssociationComponent","props","draggingElement","setState","id","value","answer","responseContainerIndex","duplicateResponses","model","updateAnswer","state","answers","possibleResponses","maxResponsePerZone","answersToStore","filter","a","containerIndex","length","answersInThisContainer","answersInOtherContainers","b","shiftedItem","shift","maxResponsePerZoneWarning","push","_","max","map","c","parseInt","isNaN","response","shouldNotPushInPossibleResponses","undefined","showCorrect","responseContainers","session","possibleResponsesWithIds","item","index","groupBy","grp","slice","flatMap","possibleResponsesFiltered","find","classes","disabled","image","stimulus","responseCorrect","validation","prompt","showDashedBorder","mode","isEvaluateMode","showToggle","validResponse","correctAnswers","forEach","container","i","images","v","warningMessage","answersToShow","hidden","visible","__html","toggleCorrect","handleOnAnswerSelect","beginDrag","handleOnDragEnd","handleOnAnswerRemove","React","Component","WarningInfo","warning","margin","backgroundColor","padding","display","alignItems","width","height","message","paddingLeft","userSelect","propTypes","PropTypes","string","object","isRequired","func","defaultProps","StyledComponent"],"mappings":"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","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport Typography from '@material-ui/core/Typography';\nimport { withDragContext } from '@pie-lib/drag';\nimport { CSSTransition, TransitionGroup } from 'react-transition-group';\nimport { ShowRationale } from '@pie-lib/icons';\nimport { Collapsible, PreviewPrompt } from '@pie-lib/render-ui';\nimport { withStyles } from '@material-ui/core/styles';\nimport CorrectAnswerToggle from '@pie-lib/correct-answer-toggle';\n\nimport Image from './image-container';\nimport InteractiveSection from './interactive-section';\nimport PossibleResponses from './possible-responses';\nimport { getUnansweredAnswers, getAnswersCorrectness } from './utils-correctness';\nimport _ from 'lodash';\n\nconst generateId = () => Math.random().toString(36).substring(2) + new Date().getTime().toString(36);\n\nconst styles = (theme) => ({\n teacherInstructions: {\n marginBottom: theme.spacing.unit * 2,\n },\n});\n\nclass ImageClozeAssociationComponent extends React.Component {\n constructor(props) {\n super(props);\n const {\n model: { possibleResponses, responseContainers, duplicateResponses, maxResponsePerZone },\n session,\n } = props;\n let { answers } = session || {};\n // set id for each possible response\n const possibleResponsesWithIds = (possibleResponses || []).map((item, index) => ({\n value: item,\n id: `${index}`,\n }));\n\n answers = _(answers || [])\n .groupBy('containerIndex')\n // keep only last maxResponsePerZone answers for each zone\n .map((grp) => grp.slice(-(maxResponsePerZone || 1)))\n .flatMap()\n // set id for each answer\n .map((answer, index) => ({ ...answer, id: `${index}` }))\n // return only answer which have a valid container index\n .filter((answer) => answer.containerIndex < responseContainers.length)\n .value();\n\n const possibleResponsesFiltered = possibleResponsesWithIds.filter(\n (response) => !answers.find((answer) => answer.value === response.value),\n );\n this.state = {\n answers: answers || [],\n draggingElement: { id: '', value: '' },\n possibleResponses: duplicateResponses ? possibleResponsesWithIds : possibleResponsesFiltered,\n // set id for each response containers\n responseContainers: responseContainers.map((item, index) => ({\n index,\n ...item,\n id: `${index}`,\n })),\n maxResponsePerZone: maxResponsePerZone || 1,\n showCorrect: false,\n };\n }\n\n beginDrag = (draggingElement) => {\n this.setState({\n draggingElement,\n });\n };\n\n handleOnDragEnd = () => {\n this.setState({\n draggingElement: { id: '', value: '' },\n });\n };\n\n handleOnAnswerSelect = (answer, responseContainerIndex) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses, maxResponsePerZone } = this.state;\n let answersToStore;\n\n if (maxResponsePerZone === answers.filter((a) => a.containerIndex === responseContainerIndex).length) {\n const answersInThisContainer = answers.filter((a) => a.containerIndex === responseContainerIndex);\n const answersInOtherContainers = answers.filter((b) => b.containerIndex !== responseContainerIndex);\n\n const shiftedItem = answersInThisContainer[0];\n if (maxResponsePerZone === 1) {\n answersInThisContainer.shift(); // FIFO\n } else {\n this.setState({ maxResponsePerZoneWarning: true });\n return;\n }\n\n // if duplicates are not allowed, make sure to put the shifted value back in possible responses\n if (!duplicateResponses) {\n possibleResponses.push({\n ...shiftedItem,\n containerIndex: '',\n id: `${_.max(possibleResponses.map((c) => parseInt(c.id)).filter((id) => !isNaN(id))) + 1}`,\n });\n }\n\n // answers will be:\n // + shifted answers for the current container\n // + if duplicatesAllowed, all the other answers from other containers\n // else: all the answers from other containers that are not having the same value\n // + new answer\n answersToStore = [\n ...answersInThisContainer, // shifted\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answersInOtherContainers.filter((a) => (duplicateResponses ? true : a.value !== answer.value)), // un-shifted\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n } else {\n // answers will be:\n // + if duplicatesAllowed, all the other answers, except the one that was dragged\n // else: all the answers that are not having the same value\n // + new answer\n answersToStore = [\n // TODO allow duplicates case Question: should we remove answer from a container if dragged to another container?\n // if yes, this should do it: add a.id !== answer.id instead of 'true'\n ...answers.filter((a) => (duplicateResponses ? a.id !== answer.id : a.value !== answer.value)),\n {\n ...answer,\n containerIndex: responseContainerIndex,\n ...(duplicateResponses ? { id: generateId() } : {}),\n },\n ];\n }\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n possibleResponses:\n // for single response per container remove answer from possible responses\n duplicateResponses\n ? possibleResponses\n : possibleResponses.filter((response) => response.value !== answer.value),\n });\n updateAnswer(answersToStore);\n };\n\n handleOnAnswerRemove = (answer) => {\n const {\n model: { duplicateResponses },\n updateAnswer,\n } = this.props;\n const { answers, possibleResponses } = this.state;\n const answersToStore = answers.filter((a) => a.id !== answer.id);\n const shouldNotPushInPossibleResponses = answer.containerIndex === undefined; // don't duplicate possible responses\n\n this.setState({\n maxResponsePerZoneWarning: false,\n answers: answersToStore,\n // push back into possible responses the removed answer if responses cannot be duplicated\n possibleResponses:\n duplicateResponses || shouldNotPushInPossibleResponses\n ? possibleResponses\n : [\n ...possibleResponses,\n {\n ...answer,\n containerIndex: undefined,\n },\n ],\n });\n updateAnswer(answersToStore);\n };\n\n toggleCorrect = (showCorrect) => this.setState({ showCorrect });\n\n render() {\n const {\n classes,\n model: {\n disabled,\n duplicateResponses,\n image,\n stimulus,\n responseCorrect,\n validation,\n teacherInstructions,\n prompt,\n showDashedBorder,\n mode,\n },\n } = this.props;\n const {\n answers,\n draggingElement,\n possibleResponses,\n responseContainers,\n maxResponsePerZone,\n maxResponsePerZoneWarning,\n showCorrect,\n } = this.state;\n const isEvaluateMode = mode === 'evaluate';\n const showToggle = isEvaluateMode && !responseCorrect;\n\n const { validResponse } = validation || {};\n const correctAnswers = [];\n\n if (validResponse) {\n (validResponse.value || []).forEach((container, i) => {\n (container.images || []).forEach((v) => {\n correctAnswers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n const warningMessage =\n `You’ve reached the limit of ${maxResponsePerZone} responses per area.` +\n 'To add another response, one must first be removed.';\n\n let answersToShow =\n responseCorrect !== undefined ? getAnswersCorrectness(answers, validation, duplicateResponses) : answers;\n\n if (responseCorrect === false && maxResponsePerZone === 1) {\n answersToShow = [...answersToShow, ...getUnansweredAnswers(answersToShow, validation)];\n }\n\n return (\n <div>\n {teacherInstructions && (\n <Collapsible\n className={classes.teacherInstructions}\n labels={{\n hidden: 'Show Teacher Instructions',\n visible: 'Hide Teacher Instructions',\n }}\n >\n <PreviewPrompt prompt={teacherInstructions} />\n </Collapsible>\n )}\n\n <PreviewPrompt className=\"prompt\" prompt={prompt} />\n\n <Typography>\n <span dangerouslySetInnerHTML={{ __html: stimulus }} />\n </Typography>\n\n <CorrectAnswerToggle show={showToggle} toggled={showCorrect} onToggle={this.toggleCorrect} />\n\n {showCorrect && showToggle ? (\n <InteractiveSection responseCorrect={true}>\n <Image\n canDrag={false}\n answers={correctAnswers}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n />\n </InteractiveSection>\n ) : (\n <InteractiveSection responseCorrect={responseCorrect}>\n <Image\n canDrag={!disabled}\n answers={answersToShow}\n draggingElement={draggingElement}\n duplicateResponses={duplicateResponses}\n image={image}\n onAnswerSelect={this.handleOnAnswerSelect}\n onDragAnswerBegin={this.beginDrag}\n onDragAnswerEnd={this.handleOnDragEnd}\n responseContainers={responseContainers}\n showDashedBorder={showDashedBorder}\n />\n\n {maxResponsePerZoneWarning && <WarningInfo message={warningMessage} />}\n\n <PossibleResponses\n canDrag={!disabled}\n data={possibleResponses}\n onAnswerRemove={this.handleOnAnswerRemove}\n onDragBegin={this.beginDrag}\n onDragEnd={this.handleOnDragEnd}\n />\n </InteractiveSection>\n )}\n </div>\n );\n }\n}\n\nconst WarningInfo = withStyles({\n warning: {\n margin: '0 16px',\n backgroundColor: '#dddddd',\n padding: '10px',\n display: 'flex',\n alignItems: 'center',\n width: 'fit-content',\n '& svg': {\n height: '30px',\n },\n '& h1': {\n padding: '0px',\n margin: '0px',\n },\n },\n message: {\n paddingLeft: '5px',\n userSelect: 'none',\n },\n})(({ classes, message }) => (\n <TransitionGroup>\n <CSSTransition classNames={'fb'} key=\"fb\" timeout={300}>\n <div key=\"panel\" className={classes.warning}>\n <ShowRationale iconSet=\"emoji\" shape=\"square\" />\n <span className={classes.message} dangerouslySetInnerHTML={{ __html: message }} />\n </div>\n </CSSTransition>\n </TransitionGroup>\n));\n\nWarningInfo.propTypes = {\n message: PropTypes.string,\n classes: PropTypes.object.isRequired,\n};\n\nImageClozeAssociationComponent.propTypes = {\n classes: PropTypes.object,\n model: PropTypes.object.isRequired,\n session: PropTypes.object,\n updateAnswer: PropTypes.func.isRequired,\n};\n\nImageClozeAssociationComponent.defaultProps = {\n classes: {},\n};\n\nconst StyledComponent = withStyles(styles)(ImageClozeAssociationComponent);\n\nexport default withDragContext(StyledComponent);\n"],"file":"root.js"}
|
package/lib/utils-correctness.js
CHANGED
|
@@ -18,7 +18,7 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
18
18
|
var getAllCorrectAnswers = function getAllCorrectAnswers(answers, responses) {
|
|
19
19
|
return answers.map(function (answer) {
|
|
20
20
|
return _objectSpread(_objectSpread({}, answer), {}, {
|
|
21
|
-
isCorrect: (responses[answer.containerIndex].images || []).includes(answer.value)
|
|
21
|
+
isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value)
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
24
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils-correctness.js"],"names":["getAllCorrectAnswers","answers","responses","map","answer","isCorrect","containerIndex","images","includes","value","getValidAnswer","response","filter","res","getUniqueCorrectAnswers","validResponses","finalAnswers","forEach","answer1","valuesToParse","answer2","length","shift","index","finalAnswer","id","valid","getUnansweredAnswers","validation","validResponse","unansweredAnswers","reduce","unanswered","isAnswered","find","hidden","getAnswersCorrectness","altResponses","allCorrect","uniqueAnswers","noOfCorrect","altUniqueStack","altResponse","altValue","altAllCorrect","sort","a","b","c"],"mappings":";;;;;;;;;;;;;;;;;AAAA,IAAMA,oBAAoB,GAAG,SAAvBA,oBAAuB,CAACC,OAAD,EAAUC,SAAV;AAAA,SAC3BD,OAAO,CAACE,GAAR,CAAY,UAACC,MAAD;AAAA,2CACPA,MADO;AAEVC,MAAAA,SAAS,EAAE,CAACH,SAAS,CAACE,MAAM,CAACE,cAAR,CAAT,CAAiCC,
|
|
1
|
+
{"version":3,"sources":["../src/utils-correctness.js"],"names":["getAllCorrectAnswers","answers","responses","map","answer","isCorrect","containerIndex","images","includes","value","getValidAnswer","response","filter","res","getUniqueCorrectAnswers","validResponses","finalAnswers","forEach","answer1","valuesToParse","answer2","length","shift","index","finalAnswer","id","valid","getUnansweredAnswers","validation","validResponse","unansweredAnswers","reduce","unanswered","isAnswered","find","hidden","getAnswersCorrectness","altResponses","allCorrect","uniqueAnswers","noOfCorrect","altUniqueStack","altResponse","altValue","altAllCorrect","sort","a","b","c"],"mappings":"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","sourcesContent":["const getAllCorrectAnswers = (answers, responses) =>\n answers.map((answer) => ({\n ...answer,\n isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value),\n }));\n\nconst getValidAnswer = (answer, response) =>\n (response[answer.containerIndex].images || []).filter((res) => res === answer.value);\n\nconst getUniqueCorrectAnswers = (answers, validResponses) => {\n let finalAnswers = answers;\n\n answers.forEach((answer1) => {\n const valuesToParse = answers.filter(\n (answer2) => answer2.value === answer1.value && answer2.containerIndex === answer1.containerIndex,\n );\n\n if (valuesToParse.length > 1) {\n // point only to duplicates but first\n valuesToParse.shift();\n // mark duplicates as incorrect\n valuesToParse.forEach((value, index) => {\n finalAnswers = finalAnswers.map((finalAnswer) => {\n if (finalAnswer.id === value.id) {\n let valid = getValidAnswer(finalAnswer, validResponses);\n\n return {\n ...finalAnswer,\n isCorrect: valid.length > index + 1,\n };\n }\n return finalAnswer;\n });\n });\n }\n });\n return finalAnswers;\n};\n\nexport const getUnansweredAnswers = (answers, validation) => {\n const { validResponse: { value } = {} } = validation;\n\n const unansweredAnswers = (value || []).reduce((unanswered, response, index) => {\n const isAnswered = !!answers.find((answer) => answer.containerIndex === index);\n\n if (!isAnswered) {\n return [\n ...unanswered,\n {\n id: `unanswered-${index}`,\n value: response.images[0] || '',\n containerIndex: index,\n isCorrect: false,\n hidden: true,\n },\n ];\n }\n\n return unanswered;\n }, []);\n\n return unansweredAnswers;\n};\n\nexport const getAnswersCorrectness = (answers, validation) => {\n const {\n validResponse: { value },\n altResponses,\n } = validation;\n\n const allCorrect = getAllCorrectAnswers(answers, value);\n const uniqueAnswers = getUniqueCorrectAnswers(allCorrect, value);\n const noOfCorrect = uniqueAnswers.filter((answer) => answer.isCorrect).length;\n\n // Look for alternate correct responses if there are incorrect responses.\n if (noOfCorrect < uniqueAnswers.length && altResponses && altResponses.length) {\n const altUniqueStack = altResponses.map((altResponse) => {\n const altValue = altResponse.value;\n\n const altAllCorrect = getAllCorrectAnswers(answers, altValue);\n return getUniqueCorrectAnswers(altAllCorrect, altValue);\n });\n // Return the one with most correct answers.\n return altUniqueStack.sort((a, b) => b.filter((c) => c.isCorrect).length - a.filter((c) => c.isCorrect).length)[0];\n }\n return uniqueAnswers;\n};\n"],"file":"utils-correctness.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/image-cloze-association",
|
|
3
|
-
"version": "4.9.1-next.
|
|
3
|
+
"version": "4.9.1-next.39+a42a408d1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "pie-framework/pie-elements",
|
|
6
6
|
"publishConfig": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"author": "pie framework developers",
|
|
23
23
|
"license": "ISC",
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "a42a408d1d238e52cbcf907fbbaec2ee98550385",
|
|
25
25
|
"scripts": {
|
|
26
26
|
"postpublish": "../../scripts/postpublish"
|
|
27
27
|
},
|
|
@@ -1,50 +1,39 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`Root snapshots model renders 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
<ImageClozeAssociationComponent
|
|
5
|
+
classes={
|
|
6
|
+
Object {
|
|
7
|
+
"teacherInstructions": "ImageClozeAssociationComponent-teacherInstructions-1",
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
model={
|
|
11
|
+
Object {
|
|
12
|
+
"answers": Array [
|
|
11
13
|
Object {
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
</WithStyles(Typography)>
|
|
17
|
-
<WithStyles(CorrectAnswerToggle)
|
|
18
|
-
onToggle={[Function]}
|
|
19
|
-
show={false}
|
|
20
|
-
toggled={false}
|
|
21
|
-
/>
|
|
22
|
-
<br />
|
|
23
|
-
<WithStyles(InteractiveSection)>
|
|
24
|
-
<WithStyles(ImageContainer)
|
|
25
|
-
answers={Array []}
|
|
26
|
-
canDrag={true}
|
|
27
|
-
draggingElement={
|
|
14
|
+
"containerIndex": 0,
|
|
15
|
+
"id": 1,
|
|
16
|
+
"value": "1",
|
|
17
|
+
},
|
|
28
18
|
Object {
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
</div>
|
|
19
|
+
"containerIndex": 1,
|
|
20
|
+
"id": 2,
|
|
21
|
+
"value": "2",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
"canDrag": true,
|
|
25
|
+
"draggingElement": Object {},
|
|
26
|
+
"duplicateResponses": false,
|
|
27
|
+
"image": Object {},
|
|
28
|
+
"maxResponsePerZone": 5,
|
|
29
|
+
"onAnswerSelect": [Function],
|
|
30
|
+
"onDragAnswerBegin": [Function],
|
|
31
|
+
"onDragAnswerEnd": [Function],
|
|
32
|
+
"possibleResponses": Array [],
|
|
33
|
+
"responseContainers": Array [],
|
|
34
|
+
"showDashedBorder": true,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
updateAnswer={[Function]}
|
|
38
|
+
/>
|
|
50
39
|
`;
|
|
@@ -53,14 +53,17 @@ InteractiveSection.defaultProps = {
|
|
|
53
53
|
responseCorrect: undefined,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
const styles = () => ({
|
|
56
|
+
const styles = (theme) => ({
|
|
57
57
|
interactiveDefault: {
|
|
58
|
+
marginTop: theme.spacing.unit * 2,
|
|
58
59
|
border: `1px solid ${color.disabled()}`,
|
|
59
60
|
},
|
|
60
61
|
interactiveCorrect: {
|
|
62
|
+
marginTop: theme.spacing.unit * 2,
|
|
61
63
|
border: `2px solid ${color.correct()}`,
|
|
62
64
|
},
|
|
63
65
|
interactiveIncorrect: {
|
|
66
|
+
marginTop: theme.spacing.unit * 2,
|
|
64
67
|
border: `2px solid ${color.incorrect()}`,
|
|
65
68
|
},
|
|
66
69
|
});
|
package/src/root.jsx
CHANGED
|
@@ -16,6 +16,12 @@ import _ from 'lodash';
|
|
|
16
16
|
|
|
17
17
|
const generateId = () => Math.random().toString(36).substring(2) + new Date().getTime().toString(36);
|
|
18
18
|
|
|
19
|
+
const styles = (theme) => ({
|
|
20
|
+
teacherInstructions: {
|
|
21
|
+
marginBottom: theme.spacing.unit * 2,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
19
25
|
class ImageClozeAssociationComponent extends React.Component {
|
|
20
26
|
constructor(props) {
|
|
21
27
|
super(props);
|
|
@@ -176,6 +182,7 @@ class ImageClozeAssociationComponent extends React.Component {
|
|
|
176
182
|
|
|
177
183
|
render() {
|
|
178
184
|
const {
|
|
185
|
+
classes,
|
|
179
186
|
model: {
|
|
180
187
|
disabled,
|
|
181
188
|
duplicateResponses,
|
|
@@ -228,10 +235,9 @@ class ImageClozeAssociationComponent extends React.Component {
|
|
|
228
235
|
|
|
229
236
|
return (
|
|
230
237
|
<div>
|
|
231
|
-
<PreviewPrompt className="prompt" prompt={prompt} />
|
|
232
|
-
|
|
233
238
|
{teacherInstructions && (
|
|
234
239
|
<Collapsible
|
|
240
|
+
className={classes.teacherInstructions}
|
|
235
241
|
labels={{
|
|
236
242
|
hidden: 'Show Teacher Instructions',
|
|
237
243
|
visible: 'Hide Teacher Instructions',
|
|
@@ -241,12 +247,13 @@ class ImageClozeAssociationComponent extends React.Component {
|
|
|
241
247
|
</Collapsible>
|
|
242
248
|
)}
|
|
243
249
|
|
|
250
|
+
<PreviewPrompt className="prompt" prompt={prompt} />
|
|
251
|
+
|
|
244
252
|
<Typography>
|
|
245
253
|
<span dangerouslySetInnerHTML={{ __html: stimulus }} />
|
|
246
254
|
</Typography>
|
|
247
255
|
|
|
248
256
|
<CorrectAnswerToggle show={showToggle} toggled={showCorrect} onToggle={this.toggleCorrect} />
|
|
249
|
-
<br />
|
|
250
257
|
|
|
251
258
|
{showCorrect && showToggle ? (
|
|
252
259
|
<InteractiveSection responseCorrect={true}>
|
|
@@ -341,4 +348,6 @@ ImageClozeAssociationComponent.defaultProps = {
|
|
|
341
348
|
classes: {},
|
|
342
349
|
};
|
|
343
350
|
|
|
344
|
-
|
|
351
|
+
const StyledComponent = withStyles(styles)(ImageClozeAssociationComponent);
|
|
352
|
+
|
|
353
|
+
export default withDragContext(StyledComponent);
|
package/src/utils-correctness.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const getAllCorrectAnswers = (answers, responses) =>
|
|
2
2
|
answers.map((answer) => ({
|
|
3
3
|
...answer,
|
|
4
|
-
isCorrect: (responses[answer.containerIndex].images || []).includes(answer.value),
|
|
4
|
+
isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value),
|
|
5
5
|
}));
|
|
6
6
|
|
|
7
7
|
const getValidAnswer = (answer, response) =>
|