@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.
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "@material-ui/core": "^3.9.2",
11
11
  "@pie-framework/pie-configure-events": "^1.3.0",
12
- "@pie-lib/pie-toolbox": "2.9.0",
12
+ "@pie-lib/pie-toolbox": "2.9.1",
13
13
  "debug": "^3.1.0",
14
14
  "prop-types": "^15.7.2",
15
15
  "react": "^16.8.6",
@@ -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: env.mode === 'evaluate' ? getScore(questionCamelized, session) === 1 : undefined
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"}
@@ -11,7 +11,7 @@
11
11
  "main": "lib/index.js",
12
12
  "module": "src/index.js",
13
13
  "dependencies": {
14
- "@pie-lib/pie-toolbox": "2.9.0",
14
+ "@pie-lib/pie-toolbox": "2.9.1",
15
15
  "debug": "^4.1.1",
16
16
  "humps": "^2.0.1",
17
17
  "lodash": "^4.17.15"
@@ -469,12 +469,7 @@ describe('controller', () => {
469
469
  });
470
470
 
471
471
  it('returns validation', () => {
472
- expect(result.validation).toEqual({
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)}`, () => {
@@ -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: env.mode === 'evaluate' ? getScore(questionCamelized, session) === 1 : undefined,
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.47+2f65ae297",
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.0",
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": "2f65ae297508c13626535290da64c2722e0af67a",
22
+ "gitHead": "84607098f90d542235187f26ad36b4e31848593d",
23
23
  "scripts": {
24
24
  "postpublish": "../../scripts/postpublish"
25
25
  },