Skip to content

Commit

Permalink
switch from error strings to error identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
handeyeco committed Jan 8, 2025
1 parent 27d6ec5 commit fb688d7
Show file tree
Hide file tree
Showing 16 changed files with 88 additions and 63 deletions.
3 changes: 1 addition & 2 deletions packages/perseus-score/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
"dependencies": {
"@khanacademy/kas": "^0.4.9",
"@khanacademy/kmath": "^0.1.24",
"@khanacademy/perseus-core": "3.0.5",
"@khanacademy/perseus": "^49.2.1"
"@khanacademy/perseus-core": "3.0.5"
},
"devDependencies": {},
"peerDependencies": {},
Expand Down
13 changes: 13 additions & 0 deletions packages/perseus-score/src/error-identifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function mark(error: string) {
return "\u2603 " + error + " \u2603";
}

export const MISSING_PERCENT_ERROR = mark("MISSING_PERCENT_ERROR");
export const NEEDS_TO_BE_SIMPLIFIED_ERROR = mark(
"NEEDS_TO_BE_SIMPLIFIED_ERROR",
);
export const APPROXIMATED_PI_ERROR = mark("APPROXIMATED_PI_ERROR");
export const EXTRA_SYMBOLS_ERROR = mark("EXTRA_SYMBOLS_ERROR");
export const WRONG_CASE_ERROR = mark("WRONG_CASE_ERROR");
export const WRONG_LETTER_ERROR = mark("WRONG_LETTER_ERROR");
export const MULTIPLICATION_SIGN_ERROR = mark("MULTIPLICATION_SIGN_ERROR");
9 changes: 9 additions & 0 deletions packages/perseus-score/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
export {default as KhanAnswerTypes} from "./util/answer-types";
export type {Score} from "./util/answer-types";
export {
APPROXIMATED_PI_ERROR,
EXTRA_SYMBOLS_ERROR,
MISSING_PERCENT_ERROR,
NEEDS_TO_BE_SIMPLIFIED_ERROR,
WRONG_CASE_ERROR,
WRONG_LETTER_ERROR,
MULTIPLICATION_SIGN_ERROR,
} from "./error-identifiers";
3 changes: 0 additions & 3 deletions packages/perseus-score/src/util/answer-types.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import {mockStrings} from "../../../perseus/src/strings";

import khanAnswerTypes from "./answer-types";

const validateFraction = (correctAnswer: string, guess: string) => {
const validator = khanAnswerTypes.number.createValidatorFunctional(
correctAnswer,
{simplified: true},
mockStrings,
);
return validator(guess);
};
Expand Down
29 changes: 16 additions & 13 deletions packages/perseus-score/src/util/answer-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ import {Errors, PerseusError} from "@khanacademy/perseus-core";
import $ from "jquery";
import _ from "underscore";

import type {PerseusStrings} from "@khanacademy/perseus/strings";
import {
APPROXIMATED_PI_ERROR,
EXTRA_SYMBOLS_ERROR,
MISSING_PERCENT_ERROR,
NEEDS_TO_BE_SIMPLIFIED_ERROR,
WRONG_CASE_ERROR,
WRONG_LETTER_ERROR,
MULTIPLICATION_SIGN_ERROR,
} from "../error-identifiers";

const MAXERROR_EPSILON = Math.pow(2, -42);

Expand Down Expand Up @@ -99,7 +107,6 @@ const KhanAnswerTypes = {
createValidatorFunctional: function (
predicate: Predicate,
options: any,
strings: PerseusStrings,
): (arg1: Guess) => Score {
// Extract the options from the given solution object
options = _.extend(
Expand Down Expand Up @@ -570,13 +577,12 @@ const KhanAnswerTypes = {
} else if (form === "percent") {
// Otherwise, an error was returned
score.empty = true;
score.message = strings.MISSING_PERCENT_ERROR;
score.message = MISSING_PERCENT_ERROR;
} else {
if (options.simplify !== "enforced") {
score.empty = true;
}
score.message =
strings.NEEDS_TO_BE_SIMPLFIED_ERROR;
score.message = NEEDS_TO_BE_SIMPLIFIED_ERROR;
}
// The return false below stops the looping of the
// callback since predicate check succeeded.
Expand All @@ -585,7 +591,7 @@ const KhanAnswerTypes = {
}
if (piApprox && predicate(val, Math.abs(val * 0.001))) {
score.empty = true;
score.message = strings.APPROXIMATED_PI_ERROR;
score.message = APPROXIMATED_PI_ERROR;
}
}
});
Expand All @@ -603,7 +609,7 @@ const KhanAnswerTypes = {
});
if (!interpretedGuess) {
score.empty = true;
score.message = strings.EXTRA_SYMBOLS_ERROR;
score.message = EXTRA_SYMBOLS_ERROR;
return score;
}
}
Expand Down Expand Up @@ -636,14 +642,12 @@ const KhanAnswerTypes = {
createValidatorFunctional: function (
correctAnswer: string,
options: any,
strings: PerseusStrings,
): (arg1: Guess) => Score {
return KhanAnswerTypes.predicate.createValidatorFunctional(
...KhanAnswerTypes.number.convertToPredicate(
correctAnswer,
options,
),
strings,
);
},
},
Expand Down Expand Up @@ -724,7 +728,6 @@ const KhanAnswerTypes = {
createValidatorFunctional: function (
solution: any,
options: any,
strings: PerseusStrings,
): (arg1: Guess) => Score {
return function (guess: Guess): Score {
const score = {
Expand Down Expand Up @@ -786,8 +789,8 @@ const KhanAnswerTypes = {
score.ungraded = true;
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
score.message = result.wrongVariableCase
? strings.WRONG_CASE_ERROR
: strings.WRONG_LETTER_ERROR;
? WRONG_CASE_ERROR
: WRONG_LETTER_ERROR;
// Don't tell the use they're "almost there" in this case, that may not be true and isn't helpful.
// @ts-expect-error - TS2339 - Property 'suppressAlmostThere' does not exist on type '{ readonly empty: false; readonly correct: false; readonly message: string | null | undefined; readonly guess: any; readonly ungraded: false; }'.
score.suppressAlmostThere = true;
Expand Down Expand Up @@ -820,7 +823,7 @@ const KhanAnswerTypes = {
// @ts-expect-error - TS2540 - Cannot assign to 'ungraded' because it is a read-only property.
score.ungraded = true;
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
score.message = strings.MULTIPLICATION_SIGN_ERROR;
score.message = MULTIPLICATION_SIGN_ERROR;
} else if (resultX.message) {
// TODO(aasmund): I18nize `score.message`
// @ts-expect-error - TS2540 - Cannot assign to 'message' because it is a read-only property.
Expand Down
1 change: 0 additions & 1 deletion packages/perseus-score/tsconfig-build.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@
{"path": "../kas/tsconfig-build.json"},
{"path": "../kmath/tsconfig-build.json"},
{"path": "../perseus-core/tsconfig-build.json"},
{"path": "../perseus/tsconfig-build.json"}
]
}
26 changes: 26 additions & 0 deletions packages/perseus/src/strings.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import {
APPROXIMATED_PI_ERROR,
EXTRA_SYMBOLS_ERROR,
MISSING_PERCENT_ERROR,
NEEDS_TO_BE_SIMPLIFIED_ERROR,
WRONG_CASE_ERROR,
WRONG_LETTER_ERROR,
MULTIPLICATION_SIGN_ERROR,
} from "@khanacademy/perseus-score";

/**
* The translated strings that are used to render Perseus.
*/
Expand Down Expand Up @@ -697,3 +707,19 @@ export const mockStrings: PerseusStrings = {
`The angle measure is ${angleMeasure} degrees with a vertex at ${vertexX} comma ${vertexY}, a point on the starting side at ${startingSideX} comma ${startingSideY} and a point on the ending side at ${endingSideX} comma ${endingSideY}.`,
// The above strings are used for interactive graph SR descriptions.
};

const errorToString = {
[MISSING_PERCENT_ERROR]: strings.MISSING_PERCENT_ERROR,
[NEEDS_TO_BE_SIMPLIFIED_ERROR]: strings.NEEDS_TO_BE_SIMPLFIED_ERROR,
[APPROXIMATED_PI_ERROR]: strings.APPROXIMATED_PI_ERROR,
[EXTRA_SYMBOLS_ERROR]: strings.EXTRA_SYMBOLS_ERROR,
[WRONG_CASE_ERROR]: strings.WRONG_CASE_ERROR,
[WRONG_LETTER_ERROR]: strings.WRONG_LETTER_ERROR,
[MULTIPLICATION_SIGN_ERROR]: strings.MULTIPLICATION_SIGN_ERROR,
};
export function mapErrorToString(err: string | null | undefined) {
if (!err) {
return err;
}
return errorToString[err] || err;
}
1 change: 0 additions & 1 deletion packages/perseus/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ function firstNumericalParse(
inexact: true,
forms: "integer, proper, improper, pi, log, mixed, decimal",
},
strings,
);

val(text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ function scoreExpression(
simplify: answer.simplify,
form: answer.form,
}),
strings,
);
};

Expand Down
10 changes: 4 additions & 6 deletions packages/perseus/src/widgets/input-number/input-number.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,10 @@ describe("invalid", function () {
options,
mockStrings,
);
expect(err).toMatchInlineSnapshot(`
{
"message": "We could not understand your answer. Please check your answer for extra text or symbols.",
"type": "invalid",
}
`);
expect(err).toEqual({
message: "☃ EXTRA_SYMBOLS_ERROR ☃",
type: "invalid",
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ describe("scoreInputNumber", () => {

const score = scoreInputNumber(useInput, rubric, mockStrings);

expect(score).toHaveInvalidInput(
"We could not understand your answer. Please check your answer for extra text or symbols.",
);
expect(score).toHaveInvalidInput("☃ EXTRA_SYMBOLS_ERROR ☃");
});

// Don't default to validating the answer as a pi answer
Expand Down
16 changes: 6 additions & 10 deletions packages/perseus/src/widgets/input-number/score-input-number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,12 @@ function scoreInputNumber(
// `KhanAnswerTypes.number.convertToPredicate`, but a string is
// expected here
const stringValue = `${rubric.value}`;
const val = KhanAnswerTypes.number.createValidatorFunctional(
stringValue,
{
simplify: rubric.simplify,
inexact: rubric.inexact || undefined,
maxError: rubric.maxError,
forms: answerTypes[rubric.answerType].forms,
},
strings,
);
const val = KhanAnswerTypes.number.createValidatorFunctional(stringValue, {
simplify: rubric.simplify,
inexact: rubric.inexact || undefined,
maxError: rubric.maxError,
forms: answerTypes[rubric.answerType].forms,
});

// We may have received TeX; try to parse it before grading.
// If `currentValue` is not TeX, this should be a no-op.
Expand Down
1 change: 0 additions & 1 deletion packages/perseus/src/widgets/matrix/score-matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function scoreMatrix(
{
simplify: true,
},
strings,
);
const result = validator(supplied[row][col]);
if (result.message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ describe("static function validate", () => {

const score = scoreNumericInput(userInput, rubric, mockStrings);

expect(score).toHaveInvalidInput(
"We could not understand your answer. Please check your answer for extra text or symbols.",
);
expect(score).toHaveInvalidInput("☃ EXTRA_SYMBOLS_ERROR ☃");
});

// Don't default to validating the answer as a pi answer
Expand Down
20 changes: 8 additions & 12 deletions packages/perseus/src/widgets/numeric-input/score-numeric-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,14 @@ function scoreNumericInput(
validatorForms.push(...defaultAnswerForms);
}

return KhanAnswerTypes.number.createValidatorFunctional(
stringAnswer,
{
message: answer.message,
simplify:
answer.status === "correct" ? answer.simplify : "optional",
inexact: true, // TODO(merlob) backfill / delete
maxError: answer.maxError,
forms: validatorForms,
},
strings,
);
return KhanAnswerTypes.number.createValidatorFunctional(stringAnswer, {
message: answer.message,
simplify:
answer.status === "correct" ? answer.simplify : "optional",
inexact: true, // TODO(merlob) backfill / delete
maxError: answer.maxError,
forms: validatorForms,
});
};

// We may have received TeX; try to parse it before grading.
Expand Down
10 changes: 3 additions & 7 deletions packages/perseus/src/widgets/table/score-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,9 @@ function scoreTable(
const rowSupplied = supplied[i];
const correct = rowSupplied.every(function (cellSupplied, i) {
const cellSolution = rowSolution[i];
const validator = createValidator(
cellSolution,
{
simplify: true,
},
strings,
);
const validator = createValidator(cellSolution, {
simplify: true,
});
const result = validator(cellSupplied);
if (result.message) {
message = result.message;
Expand Down

0 comments on commit fb688d7

Please sign in to comment.