@pie-element/image-cloze-association 6.7.2-next.47 → 6.7.2-next.56
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/configure/package.json
CHANGED
package/controller/lib/index.js
CHANGED
|
@@ -37,11 +37,14 @@ var model = function model(question, session, env) {
|
|
|
37
37
|
var questionNormalized = normalize(question);
|
|
38
38
|
var questionCamelized = (0, _humps.camelizeKeys)(questionNormalized);
|
|
39
39
|
return new Promise(function (resolve) {
|
|
40
|
+
var shouldIncludeCorrectResponse = env.mode === 'evaluate' || env.role === 'instructor' && env.mode === 'view';
|
|
41
|
+
|
|
40
42
|
var out = _objectSpread(_objectSpread({
|
|
41
43
|
disabled: env.mode !== 'gather',
|
|
42
44
|
mode: env.mode
|
|
43
45
|
}, questionCamelized), {}, {
|
|
44
|
-
responseCorrect:
|
|
46
|
+
responseCorrect: shouldIncludeCorrectResponse ? getScore(questionCamelized, session) === 1 : undefined,
|
|
47
|
+
validation: shouldIncludeCorrectResponse ? questionCamelized.validation : undefined
|
|
45
48
|
});
|
|
46
49
|
|
|
47
50
|
if (questionNormalized.shuffle) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","defaults","model","session","env","questionNormalized","questionCamelized","Promise","resolve","out","disabled","mode","responseCorrect","getScore","undefined","shuffle","possibleResponses","possible_responses","role","teacherInstructions","teacherInstructionsEnabled","rationale","isResponseCorrect","correctResponses","responses","isCorrect","totalValidResponses","forEach","value","images","length","answers","answer","index","containerIndex","indexOf","splice","keepNonEmptyResponses","filtered","filter","response","isDefaultOrAltResponseCorrect","altResponses","validation","validResponse","altResponse","getDeductionPerContainer","valid","totalStack","item","incorrectStack","maxValid","ignored","slice","getPartialScore","maxResponsePerZone","correctAnswers","incorrectAnswers","all","deductionList","id","nonEmptyResponses","denominator","str","toFixed","parseFloat","config","isPartialScoring","partialScoring","enabled","correct","outcome","score","empty","configCamelized","createCorrectResponseSession","valid_response","container","i","v","push","getInnerText","html","replaceAll","getContent","replace","validate","errors","field","required"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport { camelizeKeys } from 'humps';\nimport { partialScoring } from '@pie-lib/pie-toolbox/controller-utils';\nimport { cloneDeep, isEmpty, shuffle } from 'lodash';\n\nimport defaults from './defaults';\nimport { getAllUniqueCorrectness } from './utils';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\nexport const 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 out.rationale = questionCamelized.rationale ? questionCamelized.rationale : null;\n } else {\n out.teacherInstructions = null;\n out.rationale = null;\n }\n\n resolve(out);\n });\n};\n\nexport const isResponseCorrect = (correctResponses, session) => {\n const responses = cloneDeep(correctResponses);\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 const index = (responses[answer.containerIndex]?.images || []).indexOf(answer.value);\n\n if (index >= 0) {\n // remove response from correct responses array to ensure that duplicates are evaluated correctly\n responses[answer.containerIndex].images.splice(index, 1);\n } else {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\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 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 incorrectAnswers = 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 incorrectAnswers = 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\n if (!maxResponsePerZone || maxResponsePerZone <= 1) {\n correctAnswers -= incorrectAnswers;\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 nonEmptyResponses = keepNonEmptyResponses(validResponse.value);\n const denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).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 const 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\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 errors = {};\n\n ['teacherInstructions'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n return errors;\n};\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","defaults","model","session","env","questionNormalized","questionCamelized","Promise","resolve","shouldIncludeCorrectResponse","mode","role","out","disabled","responseCorrect","getScore","undefined","validation","shuffle","possibleResponses","possible_responses","teacherInstructions","teacherInstructionsEnabled","rationale","isResponseCorrect","correctResponses","responses","isCorrect","totalValidResponses","forEach","value","images","length","answers","answer","index","containerIndex","indexOf","splice","keepNonEmptyResponses","filtered","filter","response","isDefaultOrAltResponseCorrect","altResponses","validResponse","altResponse","getDeductionPerContainer","valid","totalStack","item","incorrectStack","maxValid","ignored","slice","getPartialScore","maxResponsePerZone","correctAnswers","incorrectAnswers","all","deductionList","id","nonEmptyResponses","denominator","str","toFixed","parseFloat","config","isPartialScoring","partialScoring","enabled","correct","outcome","score","empty","configCamelized","createCorrectResponseSession","valid_response","container","i","v","push","getInnerText","html","replaceAll","getContent","replace","validate","errors","field","required"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport { camelizeKeys } from 'humps';\nimport { partialScoring } from '@pie-lib/pie-toolbox/controller-utils';\nimport { cloneDeep, isEmpty, shuffle } from 'lodash';\n\nimport defaults from './defaults';\nimport { getAllUniqueCorrectness } from './utils';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\nexport const model = (question, session, env) => {\n const questionNormalized = normalize(question);\n const questionCamelized = camelizeKeys(questionNormalized);\n\n return new Promise((resolve) => {\n const shouldIncludeCorrectResponse = env.mode === 'evaluate' || (env.role === 'instructor' && env.mode === 'view');\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n ...questionCamelized,\n responseCorrect: shouldIncludeCorrectResponse ? getScore(questionCamelized, session) === 1 : undefined,\n validation: shouldIncludeCorrectResponse ? questionCamelized.validation : 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 out.rationale = questionCamelized.rationale ? questionCamelized.rationale : null;\n } else {\n out.teacherInstructions = null;\n out.rationale = null;\n }\n\n resolve(out);\n });\n};\n\nexport const isResponseCorrect = (correctResponses, session) => {\n const responses = cloneDeep(correctResponses);\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 const index = (responses[answer.containerIndex]?.images || []).indexOf(answer.value);\n\n if (index >= 0) {\n // remove response from correct responses array to ensure that duplicates are evaluated correctly\n responses[answer.containerIndex].images.splice(index, 1);\n } else {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\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 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 incorrectAnswers = 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 incorrectAnswers = 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\n if (!maxResponsePerZone || maxResponsePerZone <= 1) {\n correctAnswers -= incorrectAnswers;\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 nonEmptyResponses = keepNonEmptyResponses(validResponse.value);\n const denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).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 const 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\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 errors = {};\n\n ['teacherInstructions'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n return errors;\n};\n"],"file":"index.js"}
|
package/controller/package.json
CHANGED
|
@@ -469,12 +469,7 @@ describe('controller', () => {
|
|
|
469
469
|
});
|
|
470
470
|
|
|
471
471
|
it('returns validation', () => {
|
|
472
|
-
expect(result.validation).
|
|
473
|
-
validResponse: {
|
|
474
|
-
score: 1,
|
|
475
|
-
value: [{ images: [rhomb, square] }, { images: [rhomb, square, trapeze] }],
|
|
476
|
-
},
|
|
477
|
-
});
|
|
472
|
+
expect(result.validation).toBeUndefined();
|
|
478
473
|
});
|
|
479
474
|
|
|
480
475
|
it('returns responseContainers', () => {
|
|
@@ -518,6 +513,15 @@ describe('controller', () => {
|
|
|
518
513
|
return result;
|
|
519
514
|
});
|
|
520
515
|
|
|
516
|
+
it('returns validation', () => {
|
|
517
|
+
expect(result.validation).toEqual({
|
|
518
|
+
validResponse: {
|
|
519
|
+
score: 1,
|
|
520
|
+
value: [{ images: [rhomb, square] }, { images: [rhomb, square, trapeze] }],
|
|
521
|
+
},
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
521
525
|
it('returns is response correct', () => {
|
|
522
526
|
expect(result.responseCorrect).toEqual(false);
|
|
523
527
|
});
|
|
@@ -539,6 +543,36 @@ describe('controller', () => {
|
|
|
539
543
|
});
|
|
540
544
|
});
|
|
541
545
|
|
|
546
|
+
describe('validation property behavior across modes', () => {
|
|
547
|
+
it('does not include validation in gather mode', async () => {
|
|
548
|
+
const result = await model(question, {}, { mode: 'gather' });
|
|
549
|
+
|
|
550
|
+
expect(result.validation).toBeUndefined();
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('does not include validation in view mode', async () => {
|
|
554
|
+
const result = await model(question, {}, { mode: 'view' });
|
|
555
|
+
|
|
556
|
+
expect(result.validation).toBeUndefined();
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('includes validation in evaluate mode and when instructor is in view mode', async () => {
|
|
560
|
+
const evalResult = await model(question, {}, { mode: 'evaluate' });
|
|
561
|
+
const viewResult = await model(question, {}, { mode: 'view', role: 'instructor' });
|
|
562
|
+
|
|
563
|
+
expect(evalResult.validation).toBeDefined();
|
|
564
|
+
expect(viewResult.validation).toBeDefined();
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
it('ensures validation is explicitly undefined when not in evaluate or instructor view mode', async () => {
|
|
568
|
+
const gatherResult = await model(question, {}, { mode: 'gather' });
|
|
569
|
+
const studentViewResult = await model(question, {}, { mode: 'view', role: 'student' });
|
|
570
|
+
|
|
571
|
+
expect(gatherResult.validation).toBeUndefined();
|
|
572
|
+
expect(studentViewResult.validation).toBeUndefined();
|
|
573
|
+
});
|
|
574
|
+
});
|
|
575
|
+
|
|
542
576
|
describe('getPartialScore', () => {
|
|
543
577
|
const returnPartialScore = (sess) => {
|
|
544
578
|
it(`returns score of 0 if session is ${JSON.stringify(sess)}`, () => {
|
package/controller/src/index.js
CHANGED
|
@@ -15,11 +15,14 @@ export const model = (question, session, env) => {
|
|
|
15
15
|
const questionCamelized = camelizeKeys(questionNormalized);
|
|
16
16
|
|
|
17
17
|
return new Promise((resolve) => {
|
|
18
|
+
const shouldIncludeCorrectResponse = env.mode === 'evaluate' || (env.role === 'instructor' && env.mode === 'view');
|
|
19
|
+
|
|
18
20
|
const out = {
|
|
19
21
|
disabled: env.mode !== 'gather',
|
|
20
22
|
mode: env.mode,
|
|
21
23
|
...questionCamelized,
|
|
22
|
-
responseCorrect:
|
|
24
|
+
responseCorrect: shouldIncludeCorrectResponse ? getScore(questionCamelized, session) === 1 : undefined,
|
|
25
|
+
validation: shouldIncludeCorrectResponse ? questionCamelized.validation : undefined,
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
if (questionNormalized.shuffle) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/image-cloze-association",
|
|
3
|
-
"version": "6.7.2-next.
|
|
3
|
+
"version": "6.7.2-next.56+84607098f",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": "pie-framework/pie-elements",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"@material-ui/core": "^3.9.3",
|
|
11
11
|
"@material-ui/icons": "^3.0.1",
|
|
12
12
|
"@pie-framework/pie-player-events": "^0.1.0",
|
|
13
|
-
"@pie-lib/pie-toolbox": "2.9.
|
|
13
|
+
"@pie-lib/pie-toolbox": "2.9.1",
|
|
14
14
|
"classnames": "^2.2.6",
|
|
15
15
|
"humps": "^2.0.1",
|
|
16
16
|
"prop-types": "^15.6.1",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"author": "pie framework developers",
|
|
21
21
|
"license": "ISC",
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "84607098f90d542235187f26ad36b4e31848593d",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"postpublish": "../../scripts/postpublish"
|
|
25
25
|
},
|