@khanacademy/perseus-score 1.1.0 → 2.0.0

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/dist/es/index.js CHANGED
@@ -12545,13 +12545,13 @@ function validateCategorizer(userInput, validationData) {
12545
12545
  return null;
12546
12546
  }
12547
12547
 
12548
- function scoreCategorizer(userInput, scoringData) {
12549
- const validationError = validateCategorizer(userInput, scoringData);
12548
+ function scoreCategorizer(userInput, rubric) {
12549
+ const validationError = validateCategorizer(userInput, rubric);
12550
12550
  if (validationError) {
12551
12551
  return validationError;
12552
12552
  }
12553
12553
  let allCorrect = true;
12554
- scoringData.values.forEach((value, i) => {
12554
+ rubric.values.forEach((value, i) => {
12555
12555
  if (userInput.values[i] !== value) {
12556
12556
  allCorrect = false;
12557
12557
  }
@@ -12564,24 +12564,23 @@ function scoreCategorizer(userInput, scoringData) {
12564
12564
  };
12565
12565
  }
12566
12566
 
12567
- // TODO: merge this with scoreIframe, it's the same code
12568
- function scoreCSProgram(state) {
12567
+ function scoreCSProgram(userInput) {
12569
12568
  // The CS program can tell us whether it's correct or incorrect,
12570
12569
  // and pass an optional message
12571
- if (state.status === "correct") {
12570
+ if (userInput.status === "correct") {
12572
12571
  return {
12573
12572
  type: "points",
12574
12573
  earned: 1,
12575
12574
  total: 1,
12576
- message: state.message || null
12575
+ message: userInput.message || null
12577
12576
  };
12578
12577
  }
12579
- if (state.status === "incorrect") {
12578
+ if (userInput.status === "incorrect") {
12580
12579
  return {
12581
12580
  type: "points",
12582
12581
  earned: 0,
12583
12582
  total: 1,
12584
- message: state.message || null
12583
+ message: userInput.message || null
12585
12584
  };
12586
12585
  }
12587
12586
  return {
@@ -12654,9 +12653,7 @@ function validateExpression(userInput) {
12654
12653
  * show the user an error. TODO(joel) - what error?
12655
12654
  * - Otherwise, pass through the resulting points and message.
12656
12655
  */
12657
- function scoreExpression(userInput, rubric,
12658
- // TODO: remove strings as a param for scorers
12659
- strings, locale) {
12656
+ function scoreExpression(userInput, rubric, locale) {
12660
12657
  const validationError = validateExpression(userInput);
12661
12658
  if (validationError) {
12662
12659
  return validationError;
@@ -12676,7 +12673,11 @@ strings, locale) {
12676
12673
  // in the function variables list for the expression.
12677
12674
  if (!expression.parsed) {
12678
12675
  /* c8 ignore next */
12679
- throw new PerseusError("Unable to parse solution answer for expression", Errors.InvalidInput);
12676
+ throw new PerseusError("Unable to parse solution answer for expression", Errors.InvalidInput, {
12677
+ metadata: {
12678
+ rubric: JSON.stringify(rubric)
12679
+ }
12680
+ });
12680
12681
  }
12681
12682
  return KhanAnswerTypes.expression.createValidatorFunctional(expression.expr, _({}).extend(options, {
12682
12683
  simplify: answer.simplify,
@@ -13070,49 +13071,57 @@ function scoreInteractiveGraph(userInput, rubric) {
13070
13071
  };
13071
13072
  }
13072
13073
 
13074
+ function validateLabelImage(userInput) {
13075
+ let numAnswered = 0;
13076
+ for (let i = 0; i < userInput.markers.length; i++) {
13077
+ const userSelection = userInput.markers[i].selected;
13078
+ if (userSelection && userSelection.length > 0) {
13079
+ numAnswered++;
13080
+ }
13081
+ }
13082
+ // We expect all question markers to be answered before grading.
13083
+ if (numAnswered !== userInput.markers.length) {
13084
+ return {
13085
+ type: "invalid",
13086
+ message: null
13087
+ };
13088
+ }
13089
+ return null;
13090
+ }
13091
+
13073
13092
  // Question state for marker as result of user selected answers.
13074
13093
 
13075
- function scoreLabelImageMarker(marker) {
13094
+ function scoreLabelImageMarker(userInput, rubric) {
13076
13095
  const score = {
13077
13096
  hasAnswers: false,
13078
13097
  isCorrect: false
13079
13098
  };
13080
- if (marker.selected && marker.selected.length > 0) {
13099
+ if (userInput && userInput.length > 0) {
13081
13100
  score.hasAnswers = true;
13082
13101
  }
13083
- if (marker.answers.length > 0) {
13084
- if (marker.selected && marker.selected.length === marker.answers.length) {
13102
+ if (rubric.length > 0) {
13103
+ if (userInput && userInput.length === rubric.length) {
13085
13104
  // All correct answers are selected by the user.
13086
- score.isCorrect = marker.selected.every(choice => marker.answers.includes(choice));
13105
+ score.isCorrect = userInput.every(choice => rubric.includes(choice));
13087
13106
  }
13088
- } else if (!marker.selected || marker.selected.length === 0) {
13107
+ } else if (!userInput || userInput.length === 0) {
13089
13108
  // Correct as no answers should be selected by the user.
13090
13109
  score.isCorrect = true;
13091
13110
  }
13092
13111
  return score;
13093
13112
  }
13094
-
13095
- // TODO(LEMS-2440): May need to pull answers out of PerseusLabelImageWidgetOptions[markers] for the rubric
13096
13113
  function scoreLabelImage(userInput, rubric) {
13097
- let numAnswered = 0;
13114
+ const validationError = validateLabelImage(userInput);
13115
+ if (validationError) {
13116
+ return validationError;
13117
+ }
13098
13118
  let numCorrect = 0;
13099
- for (const marker of userInput.markers) {
13100
- const score = scoreLabelImageMarker(marker);
13101
- if (score.hasAnswers) {
13102
- numAnswered++;
13103
- }
13119
+ for (let i = 0; i < userInput.markers.length; i++) {
13120
+ const score = scoreLabelImageMarker(userInput.markers[i].selected, rubric.markers[i].answers);
13104
13121
  if (score.isCorrect) {
13105
13122
  numCorrect++;
13106
13123
  }
13107
13124
  }
13108
-
13109
- // We expect all question markers to be answered before grading.
13110
- if (numAnswered !== userInput.markers.length) {
13111
- return {
13112
- type: "invalid",
13113
- message: null
13114
- };
13115
- }
13116
13125
  return {
13117
13126
  type: "points",
13118
13127
  // Markers with no expected answers are graded as correct if user
@@ -13123,8 +13132,8 @@ function scoreLabelImage(userInput, rubric) {
13123
13132
  };
13124
13133
  }
13125
13134
 
13126
- function scoreMatcher(state, rubric) {
13127
- const correct = _.isEqual(state.left, rubric.left) && _.isEqual(state.right, rubric.right);
13135
+ function scoreMatcher(userInput, rubric) {
13136
+ const correct = _.isEqual(userInput.left, rubric.left) && _.isEqual(userInput.right, rubric.right);
13128
13137
  return {
13129
13138
  type: "points",
13130
13139
  earned: correct ? 1 : 0,
@@ -13141,7 +13150,7 @@ function scoreMatcher(state, rubric) {
13141
13150
  *
13142
13151
  * @see `scoreMatrix()` for more details.
13143
13152
  */
13144
- function validateMatrix(userInput, validationData) {
13153
+ function validateMatrix(userInput) {
13145
13154
  const supplied = userInput.answers;
13146
13155
  const suppliedSize = getMatrixSize(supplied);
13147
13156
  for (let row = 0; row < suppliedSize[0]; row++) {
@@ -13158,9 +13167,9 @@ function validateMatrix(userInput, validationData) {
13158
13167
  }
13159
13168
 
13160
13169
  function scoreMatrix(userInput, rubric) {
13161
- const validationResult = validateMatrix(userInput);
13162
- if (validationResult != null) {
13163
- return validationResult;
13170
+ const validationError = validateMatrix(userInput);
13171
+ if (validationError != null) {
13172
+ return validationError;
13164
13173
  }
13165
13174
  const solution = rubric.answers;
13166
13175
  const supplied = userInput.answers;
@@ -13225,16 +13234,16 @@ function validateNumberLine(userInput) {
13225
13234
  return null;
13226
13235
  }
13227
13236
 
13228
- function scoreNumberLine(userInput, scoringData) {
13237
+ function scoreNumberLine(userInput, rubric) {
13229
13238
  const validationError = validateNumberLine(userInput);
13230
13239
  if (validationError) {
13231
13240
  return validationError;
13232
13241
  }
13233
- const range = scoringData.range;
13234
- const start = scoringData.initialX != null ? scoringData.initialX : range[0];
13235
- const startRel = scoringData.isInequality ? "ge" : "eq";
13236
- const correctRel = scoringData.correctRel || "eq";
13237
- const correctPos = number.equal(userInput.numLinePosition, scoringData.correctX || 0);
13242
+ const range = rubric.range;
13243
+ const start = rubric.initialX != null ? rubric.initialX : range[0];
13244
+ const startRel = rubric.isInequality ? "ge" : "eq";
13245
+ const correctRel = rubric.correctRel || "eq";
13246
+ const correctPos = number.equal(userInput.numLinePosition, rubric.correctX || 0);
13238
13247
  if (correctPos && correctRel === userInput.rel) {
13239
13248
  return {
13240
13249
  type: "points",
@@ -13548,9 +13557,9 @@ function validateOrderer(userInput) {
13548
13557
  }
13549
13558
 
13550
13559
  function scoreOrderer(userInput, rubric) {
13551
- const validateError = validateOrderer(userInput);
13552
- if (validateError) {
13553
- return validateError;
13560
+ const validationError = validateOrderer(userInput);
13561
+ if (validationError) {
13562
+ return validationError;
13554
13563
  }
13555
13564
  const correct = _.isEqual(userInput.current, rubric.correctOptions.map(option => option.content));
13556
13565
  return {
@@ -13577,14 +13586,14 @@ function validatePlotter(userInput, validationData) {
13577
13586
  return null;
13578
13587
  }
13579
13588
 
13580
- function scorePlotter(userInput, scoringData) {
13581
- const validationError = validatePlotter(userInput, scoringData);
13589
+ function scorePlotter(userInput, rubric) {
13590
+ const validationError = validatePlotter(userInput, rubric);
13582
13591
  if (validationError) {
13583
13592
  return validationError;
13584
13593
  }
13585
13594
  return {
13586
13595
  type: "points",
13587
- earned: approximateDeepEqual(userInput, scoringData.correct) ? 1 : 0,
13596
+ earned: approximateDeepEqual(userInput, rubric.correct) ? 1 : 0,
13588
13597
  total: 1,
13589
13598
  message: null
13590
13599
  };
@@ -13836,5 +13845,5 @@ function scoreInputNumber(userInput, rubric) {
13836
13845
  };
13837
13846
  }
13838
13847
 
13839
- export { ErrorCodes, KhanAnswerTypes, inputNumberAnswerTypes, scoreCSProgram, scoreCategorizer, scoreDropdown, scoreExpression, scoreGrapher, scoreIframe, scoreInputNumber, scoreInteractiveGraph, scoreLabelImage, scoreLabelImageMarker, scoreMatcher, scoreMatrix, scoreNumberLine, scoreNumericInput, scoreOrderer, scorePlotter, scoreRadio, scoreSorter, scoreTable };
13848
+ export { ErrorCodes, KhanAnswerTypes, inputNumberAnswerTypes, scoreCSProgram, scoreCategorizer, scoreDropdown, scoreExpression, scoreGrapher, scoreIframe, scoreInputNumber, scoreInteractiveGraph, scoreLabelImage, scoreLabelImageMarker, scoreMatcher, scoreMatrix, scoreNumberLine, scoreNumericInput, scoreOrderer, scorePlotter, scoreRadio, scoreSorter, scoreTable, validateCategorizer, validateDropdown, validateExpression, validateMatrix, validateNumberLine, validateOrderer, validatePlotter, validateRadio, validateSorter, validateTable };
13840
13849
  //# sourceMappingURL=index.js.map