@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 +63 -54
- package/dist/es/index.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +72 -53
- package/dist/index.js.map +1 -1
- package/dist/validation.types.d.ts +134 -32
- package/dist/validation.typetest.d.ts +1 -0
- package/dist/widgets/categorizer/score-categorizer.d.ts +2 -2
- package/dist/widgets/cs-program/score-cs-program.d.ts +1 -1
- package/dist/widgets/expression/score-expression.d.ts +1 -1
- package/dist/widgets/grapher/score-grapher.d.ts +1 -1
- package/dist/widgets/interactive-graph/score-interactive-graph.d.ts +1 -1
- package/dist/widgets/label-image/score-label-image.d.ts +2 -3
- package/dist/widgets/label-image/validate-label-image.d.ts +3 -0
- package/dist/widgets/matcher/score-matcher.d.ts +1 -1
- package/dist/widgets/matrix/score-matrix.d.ts +1 -1
- package/dist/widgets/matrix/validate-matrix.d.ts +2 -2
- package/dist/widgets/number-line/score-number-line.d.ts +2 -2
- package/dist/widgets/plotter/score-plotter.d.ts +2 -2
- package/dist/widgets/sorter/score-sorter.d.ts +1 -1
- package/dist/widgets/table/score-table.d.ts +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -3,20 +3,30 @@ export type { Score } from "./util/answer-types";
|
|
|
3
3
|
export { default as ErrorCodes } from "./error-codes";
|
|
4
4
|
export type * from "./validation.types";
|
|
5
5
|
export { default as scoreCategorizer } from "./widgets/categorizer/score-categorizer";
|
|
6
|
+
export { default as validateCategorizer } from "./widgets/categorizer/validate-categorizer";
|
|
6
7
|
export { default as scoreCSProgram } from "./widgets/cs-program/score-cs-program";
|
|
7
8
|
export { default as scoreDropdown } from "./widgets/dropdown/score-dropdown";
|
|
9
|
+
export { default as validateDropdown } from "./widgets/dropdown/validate-dropdown";
|
|
8
10
|
export { default as scoreExpression } from "./widgets/expression/score-expression";
|
|
11
|
+
export { default as validateExpression } from "./widgets/expression/validate-expression";
|
|
9
12
|
export { default as scoreGrapher } from "./widgets/grapher/score-grapher";
|
|
10
13
|
export { default as scoreIframe } from "./widgets/iframe/score-iframe";
|
|
11
14
|
export { default as scoreInteractiveGraph } from "./widgets/interactive-graph/score-interactive-graph";
|
|
12
15
|
export { default as scoreLabelImage, scoreLabelImageMarker, } from "./widgets/label-image/score-label-image";
|
|
13
16
|
export { default as scoreMatcher } from "./widgets/matcher/score-matcher";
|
|
14
17
|
export { default as scoreMatrix } from "./widgets/matrix/score-matrix";
|
|
18
|
+
export { default as validateMatrix } from "./widgets/matrix/validate-matrix";
|
|
15
19
|
export { default as scoreNumberLine } from "./widgets/number-line/score-number-line";
|
|
20
|
+
export { default as validateNumberLine } from "./widgets/number-line/validate-number-line";
|
|
16
21
|
export { default as scoreNumericInput } from "./widgets/numeric-input/score-numeric-input";
|
|
17
22
|
export { default as scoreOrderer } from "./widgets/orderer/score-orderer";
|
|
23
|
+
export { default as validateOrderer } from "./widgets/orderer/validate-orderer";
|
|
18
24
|
export { default as scorePlotter } from "./widgets/plotter/score-plotter";
|
|
25
|
+
export { default as validatePlotter } from "./widgets/plotter/validate-plotter";
|
|
19
26
|
export { default as scoreRadio } from "./widgets/radio/score-radio";
|
|
27
|
+
export { default as validateRadio } from "./widgets/radio/validate-radio";
|
|
20
28
|
export { default as scoreSorter } from "./widgets/sorter/score-sorter";
|
|
29
|
+
export { default as validateSorter } from "./widgets/sorter/validate-sorter";
|
|
21
30
|
export { default as scoreTable } from "./widgets/table/score-table";
|
|
31
|
+
export { default as validateTable } from "./widgets/table/validate-table";
|
|
22
32
|
export { default as scoreInputNumber, inputNumberAnswerTypes, } from "./widgets/input-number/score-input-number";
|
package/dist/index.js
CHANGED
|
@@ -12570,13 +12570,13 @@ function validateCategorizer(userInput, validationData) {
|
|
|
12570
12570
|
return null;
|
|
12571
12571
|
}
|
|
12572
12572
|
|
|
12573
|
-
function scoreCategorizer(userInput,
|
|
12574
|
-
const validationError = validateCategorizer(userInput,
|
|
12573
|
+
function scoreCategorizer(userInput, rubric) {
|
|
12574
|
+
const validationError = validateCategorizer(userInput, rubric);
|
|
12575
12575
|
if (validationError) {
|
|
12576
12576
|
return validationError;
|
|
12577
12577
|
}
|
|
12578
12578
|
let allCorrect = true;
|
|
12579
|
-
|
|
12579
|
+
rubric.values.forEach((value, i) => {
|
|
12580
12580
|
if (userInput.values[i] !== value) {
|
|
12581
12581
|
allCorrect = false;
|
|
12582
12582
|
}
|
|
@@ -12589,24 +12589,23 @@ function scoreCategorizer(userInput, scoringData) {
|
|
|
12589
12589
|
};
|
|
12590
12590
|
}
|
|
12591
12591
|
|
|
12592
|
-
|
|
12593
|
-
function scoreCSProgram(state) {
|
|
12592
|
+
function scoreCSProgram(userInput) {
|
|
12594
12593
|
// The CS program can tell us whether it's correct or incorrect,
|
|
12595
12594
|
// and pass an optional message
|
|
12596
|
-
if (
|
|
12595
|
+
if (userInput.status === "correct") {
|
|
12597
12596
|
return {
|
|
12598
12597
|
type: "points",
|
|
12599
12598
|
earned: 1,
|
|
12600
12599
|
total: 1,
|
|
12601
|
-
message:
|
|
12600
|
+
message: userInput.message || null
|
|
12602
12601
|
};
|
|
12603
12602
|
}
|
|
12604
|
-
if (
|
|
12603
|
+
if (userInput.status === "incorrect") {
|
|
12605
12604
|
return {
|
|
12606
12605
|
type: "points",
|
|
12607
12606
|
earned: 0,
|
|
12608
12607
|
total: 1,
|
|
12609
|
-
message:
|
|
12608
|
+
message: userInput.message || null
|
|
12610
12609
|
};
|
|
12611
12610
|
}
|
|
12612
12611
|
return {
|
|
@@ -12679,9 +12678,7 @@ function validateExpression(userInput) {
|
|
|
12679
12678
|
* show the user an error. TODO(joel) - what error?
|
|
12680
12679
|
* - Otherwise, pass through the resulting points and message.
|
|
12681
12680
|
*/
|
|
12682
|
-
function scoreExpression(userInput, rubric,
|
|
12683
|
-
// TODO: remove strings as a param for scorers
|
|
12684
|
-
strings, locale) {
|
|
12681
|
+
function scoreExpression(userInput, rubric, locale) {
|
|
12685
12682
|
const validationError = validateExpression(userInput);
|
|
12686
12683
|
if (validationError) {
|
|
12687
12684
|
return validationError;
|
|
@@ -12701,7 +12698,11 @@ strings, locale) {
|
|
|
12701
12698
|
// in the function variables list for the expression.
|
|
12702
12699
|
if (!expression.parsed) {
|
|
12703
12700
|
/* c8 ignore next */
|
|
12704
|
-
throw new perseusCore.PerseusError("Unable to parse solution answer for expression", perseusCore.Errors.InvalidInput
|
|
12701
|
+
throw new perseusCore.PerseusError("Unable to parse solution answer for expression", perseusCore.Errors.InvalidInput, {
|
|
12702
|
+
metadata: {
|
|
12703
|
+
rubric: JSON.stringify(rubric)
|
|
12704
|
+
}
|
|
12705
|
+
});
|
|
12705
12706
|
}
|
|
12706
12707
|
return KhanAnswerTypes.expression.createValidatorFunctional(expression.expr, _({}).extend(options, {
|
|
12707
12708
|
simplify: answer.simplify,
|
|
@@ -13095,49 +13096,57 @@ function scoreInteractiveGraph(userInput, rubric) {
|
|
|
13095
13096
|
};
|
|
13096
13097
|
}
|
|
13097
13098
|
|
|
13099
|
+
function validateLabelImage(userInput) {
|
|
13100
|
+
let numAnswered = 0;
|
|
13101
|
+
for (let i = 0; i < userInput.markers.length; i++) {
|
|
13102
|
+
const userSelection = userInput.markers[i].selected;
|
|
13103
|
+
if (userSelection && userSelection.length > 0) {
|
|
13104
|
+
numAnswered++;
|
|
13105
|
+
}
|
|
13106
|
+
}
|
|
13107
|
+
// We expect all question markers to be answered before grading.
|
|
13108
|
+
if (numAnswered !== userInput.markers.length) {
|
|
13109
|
+
return {
|
|
13110
|
+
type: "invalid",
|
|
13111
|
+
message: null
|
|
13112
|
+
};
|
|
13113
|
+
}
|
|
13114
|
+
return null;
|
|
13115
|
+
}
|
|
13116
|
+
|
|
13098
13117
|
// Question state for marker as result of user selected answers.
|
|
13099
13118
|
|
|
13100
|
-
function scoreLabelImageMarker(
|
|
13119
|
+
function scoreLabelImageMarker(userInput, rubric) {
|
|
13101
13120
|
const score = {
|
|
13102
13121
|
hasAnswers: false,
|
|
13103
13122
|
isCorrect: false
|
|
13104
13123
|
};
|
|
13105
|
-
if (
|
|
13124
|
+
if (userInput && userInput.length > 0) {
|
|
13106
13125
|
score.hasAnswers = true;
|
|
13107
13126
|
}
|
|
13108
|
-
if (
|
|
13109
|
-
if (
|
|
13127
|
+
if (rubric.length > 0) {
|
|
13128
|
+
if (userInput && userInput.length === rubric.length) {
|
|
13110
13129
|
// All correct answers are selected by the user.
|
|
13111
|
-
score.isCorrect =
|
|
13130
|
+
score.isCorrect = userInput.every(choice => rubric.includes(choice));
|
|
13112
13131
|
}
|
|
13113
|
-
} else if (!
|
|
13132
|
+
} else if (!userInput || userInput.length === 0) {
|
|
13114
13133
|
// Correct as no answers should be selected by the user.
|
|
13115
13134
|
score.isCorrect = true;
|
|
13116
13135
|
}
|
|
13117
13136
|
return score;
|
|
13118
13137
|
}
|
|
13119
|
-
|
|
13120
|
-
// TODO(LEMS-2440): May need to pull answers out of PerseusLabelImageWidgetOptions[markers] for the rubric
|
|
13121
13138
|
function scoreLabelImage(userInput, rubric) {
|
|
13122
|
-
|
|
13139
|
+
const validationError = validateLabelImage(userInput);
|
|
13140
|
+
if (validationError) {
|
|
13141
|
+
return validationError;
|
|
13142
|
+
}
|
|
13123
13143
|
let numCorrect = 0;
|
|
13124
|
-
for (
|
|
13125
|
-
const score = scoreLabelImageMarker(
|
|
13126
|
-
if (score.hasAnswers) {
|
|
13127
|
-
numAnswered++;
|
|
13128
|
-
}
|
|
13144
|
+
for (let i = 0; i < userInput.markers.length; i++) {
|
|
13145
|
+
const score = scoreLabelImageMarker(userInput.markers[i].selected, rubric.markers[i].answers);
|
|
13129
13146
|
if (score.isCorrect) {
|
|
13130
13147
|
numCorrect++;
|
|
13131
13148
|
}
|
|
13132
13149
|
}
|
|
13133
|
-
|
|
13134
|
-
// We expect all question markers to be answered before grading.
|
|
13135
|
-
if (numAnswered !== userInput.markers.length) {
|
|
13136
|
-
return {
|
|
13137
|
-
type: "invalid",
|
|
13138
|
-
message: null
|
|
13139
|
-
};
|
|
13140
|
-
}
|
|
13141
13150
|
return {
|
|
13142
13151
|
type: "points",
|
|
13143
13152
|
// Markers with no expected answers are graded as correct if user
|
|
@@ -13148,8 +13157,8 @@ function scoreLabelImage(userInput, rubric) {
|
|
|
13148
13157
|
};
|
|
13149
13158
|
}
|
|
13150
13159
|
|
|
13151
|
-
function scoreMatcher(
|
|
13152
|
-
const correct = _.isEqual(
|
|
13160
|
+
function scoreMatcher(userInput, rubric) {
|
|
13161
|
+
const correct = _.isEqual(userInput.left, rubric.left) && _.isEqual(userInput.right, rubric.right);
|
|
13153
13162
|
return {
|
|
13154
13163
|
type: "points",
|
|
13155
13164
|
earned: correct ? 1 : 0,
|
|
@@ -13166,7 +13175,7 @@ function scoreMatcher(state, rubric) {
|
|
|
13166
13175
|
*
|
|
13167
13176
|
* @see `scoreMatrix()` for more details.
|
|
13168
13177
|
*/
|
|
13169
|
-
function validateMatrix(userInput
|
|
13178
|
+
function validateMatrix(userInput) {
|
|
13170
13179
|
const supplied = userInput.answers;
|
|
13171
13180
|
const suppliedSize = perseusCore.getMatrixSize(supplied);
|
|
13172
13181
|
for (let row = 0; row < suppliedSize[0]; row++) {
|
|
@@ -13183,9 +13192,9 @@ function validateMatrix(userInput, validationData) {
|
|
|
13183
13192
|
}
|
|
13184
13193
|
|
|
13185
13194
|
function scoreMatrix(userInput, rubric) {
|
|
13186
|
-
const
|
|
13187
|
-
if (
|
|
13188
|
-
return
|
|
13195
|
+
const validationError = validateMatrix(userInput);
|
|
13196
|
+
if (validationError != null) {
|
|
13197
|
+
return validationError;
|
|
13189
13198
|
}
|
|
13190
13199
|
const solution = rubric.answers;
|
|
13191
13200
|
const supplied = userInput.answers;
|
|
@@ -13250,16 +13259,16 @@ function validateNumberLine(userInput) {
|
|
|
13250
13259
|
return null;
|
|
13251
13260
|
}
|
|
13252
13261
|
|
|
13253
|
-
function scoreNumberLine(userInput,
|
|
13262
|
+
function scoreNumberLine(userInput, rubric) {
|
|
13254
13263
|
const validationError = validateNumberLine(userInput);
|
|
13255
13264
|
if (validationError) {
|
|
13256
13265
|
return validationError;
|
|
13257
13266
|
}
|
|
13258
|
-
const range =
|
|
13259
|
-
const start =
|
|
13260
|
-
const startRel =
|
|
13261
|
-
const correctRel =
|
|
13262
|
-
const correctPos = kmath.number.equal(userInput.numLinePosition,
|
|
13267
|
+
const range = rubric.range;
|
|
13268
|
+
const start = rubric.initialX != null ? rubric.initialX : range[0];
|
|
13269
|
+
const startRel = rubric.isInequality ? "ge" : "eq";
|
|
13270
|
+
const correctRel = rubric.correctRel || "eq";
|
|
13271
|
+
const correctPos = kmath.number.equal(userInput.numLinePosition, rubric.correctX || 0);
|
|
13263
13272
|
if (correctPos && correctRel === userInput.rel) {
|
|
13264
13273
|
return {
|
|
13265
13274
|
type: "points",
|
|
@@ -13562,9 +13571,9 @@ function validateOrderer(userInput) {
|
|
|
13562
13571
|
}
|
|
13563
13572
|
|
|
13564
13573
|
function scoreOrderer(userInput, rubric) {
|
|
13565
|
-
const
|
|
13566
|
-
if (
|
|
13567
|
-
return
|
|
13574
|
+
const validationError = validateOrderer(userInput);
|
|
13575
|
+
if (validationError) {
|
|
13576
|
+
return validationError;
|
|
13568
13577
|
}
|
|
13569
13578
|
const correct = _.isEqual(userInput.current, rubric.correctOptions.map(option => option.content));
|
|
13570
13579
|
return {
|
|
@@ -13591,14 +13600,14 @@ function validatePlotter(userInput, validationData) {
|
|
|
13591
13600
|
return null;
|
|
13592
13601
|
}
|
|
13593
13602
|
|
|
13594
|
-
function scorePlotter(userInput,
|
|
13595
|
-
const validationError = validatePlotter(userInput,
|
|
13603
|
+
function scorePlotter(userInput, rubric) {
|
|
13604
|
+
const validationError = validatePlotter(userInput, rubric);
|
|
13596
13605
|
if (validationError) {
|
|
13597
13606
|
return validationError;
|
|
13598
13607
|
}
|
|
13599
13608
|
return {
|
|
13600
13609
|
type: "points",
|
|
13601
|
-
earned: perseusCore.approximateDeepEqual(userInput,
|
|
13610
|
+
earned: perseusCore.approximateDeepEqual(userInput, rubric.correct) ? 1 : 0,
|
|
13602
13611
|
total: 1,
|
|
13603
13612
|
message: null
|
|
13604
13613
|
};
|
|
@@ -13872,4 +13881,14 @@ exports.scorePlotter = scorePlotter;
|
|
|
13872
13881
|
exports.scoreRadio = scoreRadio;
|
|
13873
13882
|
exports.scoreSorter = scoreSorter;
|
|
13874
13883
|
exports.scoreTable = scoreTable;
|
|
13884
|
+
exports.validateCategorizer = validateCategorizer;
|
|
13885
|
+
exports.validateDropdown = validateDropdown;
|
|
13886
|
+
exports.validateExpression = validateExpression;
|
|
13887
|
+
exports.validateMatrix = validateMatrix;
|
|
13888
|
+
exports.validateNumberLine = validateNumberLine;
|
|
13889
|
+
exports.validateOrderer = validateOrderer;
|
|
13890
|
+
exports.validatePlotter = validatePlotter;
|
|
13891
|
+
exports.validateRadio = validateRadio;
|
|
13892
|
+
exports.validateSorter = validateSorter;
|
|
13893
|
+
exports.validateTable = validateTable;
|
|
13875
13894
|
//# sourceMappingURL=index.js.map
|