@pie-element/image-cloze-association 4.11.2 → 4.11.3-next.12

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.
@@ -106,7 +106,6 @@ var keepNonEmptyResponses = function keepNonEmptyResponses(responses) {
106
106
  var isDefaultOrAltResponseCorrect = function isDefaultOrAltResponseCorrect(question, session) {
107
107
  var altResponses = question.validation.altResponses;
108
108
  var value = question.validation.validResponse.value;
109
- value = keepNonEmptyResponses(value);
110
109
  var isCorrect = isResponseCorrect(value, session); // Look for correct answers in alternate responses.
111
110
 
112
111
  if (!isCorrect && altResponses && altResponses.length) {
@@ -142,13 +141,13 @@ var getPartialScore = function getPartialScore(question, session) {
142
141
  var validResponse = question.validation.validResponse,
143
142
  maxResponsePerZone = question.maxResponsePerZone;
144
143
  var correctAnswers = 0;
144
+ var incorrectAnswers = 0;
145
145
  var possibleResponses = 0;
146
146
 
147
147
  if (!session || (0, _isEmpty["default"])(session)) {
148
148
  return 0;
149
149
  }
150
150
 
151
- validResponse.value = keepNonEmptyResponses(validResponse.value);
152
151
  validResponse.value.forEach(function (value) {
153
152
  return possibleResponses += (value.images || []).length;
154
153
  });
@@ -157,6 +156,9 @@ var getPartialScore = function getPartialScore(question, session) {
157
156
  var all = (0, _utils.getAllUniqueCorrectness)(session.answers, validResponse.value);
158
157
  correctAnswers = all.filter(function (item) {
159
158
  return item.isCorrect;
159
+ }).length;
160
+ incorrectAnswers = all.filter(function (item) {
161
+ return !item.isCorrect;
160
162
  }).length; // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit
161
163
 
162
164
  session.answers.forEach(function (answer) {
@@ -172,6 +174,10 @@ var getPartialScore = function getPartialScore(question, session) {
172
174
  }
173
175
  }
174
176
  });
177
+
178
+ if (!maxResponsePerZone || maxResponsePerZone <= 1) {
179
+ correctAnswers -= incorrectAnswers;
180
+ }
175
181
  } else {
176
182
  correctAnswers = 0;
177
183
  } // negative values will implicitly make the score equal to zero
@@ -179,7 +185,8 @@ var getPartialScore = function getPartialScore(question, session) {
179
185
 
180
186
  correctAnswers = correctAnswers < 0 ? 0 : correctAnswers; // use length of validResponse since some containers can be left empty
181
187
 
182
- var denominator = maxResponsePerZone > 1 ? possibleResponses : (validResponse.value || []).length;
188
+ var nonEmptyResponses = keepNonEmptyResponses(validResponse.value);
189
+ var denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).length;
183
190
  var str = (correctAnswers / denominator).toFixed(2);
184
191
  return parseFloat(str);
185
192
  };
@@ -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","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"}
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","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"],"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 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 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 +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,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"}
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,SAAwBD,OAAO,CAACE,GAAR,CAAY,UAACC,MAAD;AAAA,2CACvDA,MADuD;AAE1DC,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;AAF+C;AAAA,GAAZ,CAAxB;AAAA,CAA1B;;AAKA,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) => 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"}
@@ -215,6 +215,41 @@ describe('controller', () => {
215
215
  expect(result.score).toEqual(0.5);
216
216
  });
217
217
 
218
+ it('returns correct score for valid response with empty response containers, incorrect answers and partialScoring: true', async () => {
219
+ const result = await outcome({
220
+ ...question,
221
+ partialScoring: true,
222
+ validation: {
223
+ valid_response: {
224
+ score: 1,
225
+ value: [
226
+ {
227
+ images: [rhomb],
228
+ },
229
+ {
230
+ images: [],
231
+ },
232
+ {
233
+ images: [rhomb],
234
+ },
235
+ {
236
+ images: [],
237
+ },
238
+ ],
239
+ },
240
+ }
241
+ }, {
242
+ answers: [
243
+ { value: rhomb, containerIndex: 0 },
244
+ { value: rhomb, containerIndex: 1 },
245
+ { value: rhomb, containerIndex: 2 },
246
+ { value: rhomb, containerIndex: 3 },
247
+ ],
248
+ });
249
+
250
+ expect(result.score).toEqual(0);
251
+ });
252
+
218
253
  describe('returns score 0 for wrong validation format', () => {
219
254
  it('returns 0 for old value format', async () => {
220
255
  const result = await outcome(
@@ -83,8 +83,6 @@ const isDefaultOrAltResponseCorrect = (question, session) => {
83
83
  }
84
84
  } = question;
85
85
 
86
- value = keepNonEmptyResponses(value);
87
-
88
86
  let isCorrect = isResponseCorrect(value, session);
89
87
 
90
88
  // Look for correct answers in alternate responses.
@@ -117,18 +115,19 @@ export const getPartialScore = (question, session) => {
117
115
  maxResponsePerZone,
118
116
  } = question;
119
117
  let correctAnswers = 0;
118
+ let incorrectAnswers = 0;
120
119
  let possibleResponses = 0;
121
120
 
122
121
  if (!session || isEmpty(session)) {
123
122
  return 0;
124
123
  }
125
- validResponse.value = keepNonEmptyResponses(validResponse.value);
126
124
 
127
125
  validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));
128
126
 
129
127
  if (session.answers && session.answers.length) {
130
128
  const all = getAllUniqueCorrectness(session.answers, validResponse.value);
131
129
  correctAnswers = all.filter((item) => item.isCorrect).length;
130
+ incorrectAnswers = all.filter((item) => !item.isCorrect).length;
132
131
 
133
132
  // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit
134
133
  session.answers.forEach((answer) => {
@@ -144,6 +143,10 @@ export const getPartialScore = (question, session) => {
144
143
  }
145
144
  }
146
145
  });
146
+
147
+ if (!maxResponsePerZone || maxResponsePerZone <= 1) {
148
+ correctAnswers -= incorrectAnswers;
149
+ }
147
150
  } else {
148
151
  correctAnswers = 0;
149
152
  }
@@ -151,7 +154,8 @@ export const getPartialScore = (question, session) => {
151
154
  correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;
152
155
 
153
156
  // use length of validResponse since some containers can be left empty
154
- const denominator = maxResponsePerZone > 1 ? possibleResponses : (validResponse.value || []).length;
157
+ const nonEmptyResponses = keepNonEmptyResponses(validResponse.value);
158
+ const denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).length;
155
159
  const str = (correctAnswers / denominator).toFixed(2);
156
160
 
157
161
  return parseFloat(str);
@@ -1,8 +1,7 @@
1
- const getAllCorrectness = (answers, responses) =>
2
- answers.map((answer) => ({
1
+ const getAllCorrectness = (answers, responses) => answers.map((answer) => ({
3
2
  ...answer,
4
3
  isCorrect: (responses[answer.containerIndex] && responses[answer.containerIndex].images || []).includes(answer.value),
5
- }));
4
+ }));
6
5
 
7
6
  const getValidAnswer = (answer, response) =>
8
7
  (response[answer.containerIndex] && response[answer.containerIndex].images || []).filter((res) => res === answer.value);
@@ -61,7 +61,7 @@ var getUnansweredAnswers = function getUnansweredAnswers(answers, validation) {
61
61
  var _validation$validResp = validation.validResponse;
62
62
  _validation$validResp = _validation$validResp === void 0 ? {} : _validation$validResp;
63
63
  var value = _validation$validResp.value;
64
- var unansweredAnswers = (value || []).reduce(function (unanswered, response, index) {
64
+ return (value || []).reduce(function (unanswered, response, index) {
65
65
  var isAnswered = !!answers.find(function (answer) {
66
66
  return answer.containerIndex === index;
67
67
  });
@@ -71,14 +71,13 @@ var getUnansweredAnswers = function getUnansweredAnswers(answers, validation) {
71
71
  id: "unanswered-".concat(index),
72
72
  value: response.images[0] || '',
73
73
  containerIndex: index,
74
- isCorrect: false,
74
+ isCorrect: !response.images.length ? undefined : false,
75
75
  hidden: true
76
76
  }]);
77
77
  }
78
78
 
79
79
  return unanswered;
80
80
  }, []);
81
- return unansweredAnswers;
82
81
  };
83
82
 
84
83
  exports.getUnansweredAnswers = getUnansweredAnswers;
@@ -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":"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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"}
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","reduce","unanswered","isAnswered","find","undefined","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 return (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: !response.images.length ? undefined : false,\n hidden: true,\n },\n ];\n }\n\n return unanswered;\n }, []);\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.11.2",
3
+ "version": "4.11.3-next.12+52611f46c",
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": "6e11b6009ac44f9c404de46777dd756d1ef38eed",
24
+ "gitHead": "52611f46c1ec29312ffa471d5970ddecc7be8803",
25
25
  "scripts": {
26
26
  "postpublish": "../../scripts/postpublish"
27
27
  },
@@ -40,7 +40,7 @@ const getUniqueCorrectAnswers = (answers, validResponses) => {
40
40
  export const getUnansweredAnswers = (answers, validation) => {
41
41
  const { validResponse: { value } = {} } = validation;
42
42
 
43
- const unansweredAnswers = (value || []).reduce((unanswered, response, index) => {
43
+ return (value || []).reduce((unanswered, response, index) => {
44
44
  const isAnswered = !!answers.find((answer) => answer.containerIndex === index);
45
45
 
46
46
  if (!isAnswered) {
@@ -50,7 +50,7 @@ export const getUnansweredAnswers = (answers, validation) => {
50
50
  id: `unanswered-${index}`,
51
51
  value: response.images[0] || '',
52
52
  containerIndex: index,
53
- isCorrect: false,
53
+ isCorrect: !response.images.length ? undefined : false,
54
54
  hidden: true,
55
55
  },
56
56
  ];
@@ -58,8 +58,6 @@ export const getUnansweredAnswers = (answers, validation) => {
58
58
 
59
59
  return unanswered;
60
60
  }, []);
61
-
62
- return unansweredAnswers;
63
61
  };
64
62
 
65
63
  export const getAnswersCorrectness = (answers, validation) => {