Skip to content

docs(changeset): Ensure that extra keys are considered when determining whether an Expression Widget answer is invalid.#3292

Open
SonicScrewdriver wants to merge 3 commits intomainfrom
extra-keys-extra-attention
Open

docs(changeset): Ensure that extra keys are considered when determining whether an Expression Widget answer is invalid.#3292
SonicScrewdriver wants to merge 3 commits intomainfrom
extra-keys-extra-attention

Conversation

@SonicScrewdriver
Copy link
Contributor

@SonicScrewdriver SonicScrewdriver commented Feb 27, 2026

Summary:

We ran into an issue where the Expression Widget was returning invalid when the user used a variable that the Content Creators had explicitly used in a "wrong" answer.

I've added new logic to KAS to handle this situation. I opted to add most of the logic to sameVar, as that seemed like the most logical place for it to be due to it only being used for the Expression widget. However, I'm open to push back on this. :)

Update Note: While re-reviewing, I took the opportunity to rename sameVars to validateVars and update its return type. sameVars was really only being used to surface specific variable errors, so I'm not sure the name was ever quite right. With my changes, I think validateVars improves code readability. I also folded the !equal guard into hasWrongVarCase directly, which allowed me to make the return more self-explanatory while simplifying the logic in compare.ts. I'm fully open to push back on this one, however — I just got bold. ;)

Issue: LEMS-3566

Test plan:

  • Existing tests pass
  • New tests pass
  • Tests pass in frontend
  • Manual testing in frontend

…riableNames error when the variables are provided in the extra keys
…are considered when determining whether an Expression Widget answer is invalid.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

🗄️ Schema Change: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

Size Change: +64 B (+0.01%)

Total Size: 485 kB

Filename Size Change
packages/kas/dist/es/index.js 20.8 kB +64 B (+0.31%)
ℹ️ View Unchanged
Filename Size
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 5.96 kB
packages/math-input/dist/es/index.js 98.5 kB
packages/math-input/dist/es/strings.js 1.61 kB
packages/perseus-core/dist/es/index.item-splitting.js 11.8 kB
packages/perseus-core/dist/es/index.js 24.9 kB
packages/perseus-editor/dist/es/index.js 99.4 kB
packages/perseus-linter/dist/es/index.js 8.83 kB
packages/perseus-score/dist/es/index.js 9.26 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/index.js 187 kB
packages/perseus/dist/es/strings.js 7.49 kB
packages/pure-markdown/dist/es/index.js 1.39 kB
packages/simple-markdown/dist/es/index.js 6.71 kB

compressed-size-action

@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

🛠️ Item Splitting: No Changes ✅

@github-actions
Copy link
Contributor

github-actions bot commented Feb 27, 2026

npm Snapshot: Published

Good news!! We've packaged up the latest commit from this PR (86910eb) and published it to npm. You
can install it using the tag PR3292.

Example:

pnpm add @khanacademy/perseus@PR3292

If you are working in Khan Academy's frontend, you can run the below command.

./dev/tools/bump_perseus_version.ts -t PR3292

If you are working in Khan Academy's webapp, you can run the below command.

./dev/tools/bump_perseus_version.js -t PR3292

message =
// Variable checks
const vars = expr1.sameVars(expr2, optionsWithDefaults.extraKeys);
if (!vars.equal && vars.equalIgnoringCase) {
Copy link
Contributor Author

@SonicScrewdriver SonicScrewdriver Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opted to split this into two returns in order to improve clarity after the addition of hasUnexpectedVars. We could keep the logic consolidated, I just found the if statement(s) far easier to read this way.

simplify: boolean;
// Variables from other answer forms (e.g. intentionally wrong answers) that
// are "known" — students using these should be considered to have valid answers
extraKeys?: ReadonlyArray<string>;
Copy link
Contributor Author

@SonicScrewdriver SonicScrewdriver Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a specific type (KeypadKey) that ExpressionWidget uses for extraKeys, but there's notes in data-schema.ts that says we shouldn't be using it, so I've just opted for a simple array of strings.

@@ -395,7 +397,13 @@ abstract class Expr {
var equal = same(vars1, vars2);
var equalIgnoringCase = same(lower(vars1), lower(vars2));
Copy link
Contributor Author

@SonicScrewdriver SonicScrewdriver Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a thought here, but I'm not sure the best approach.

I kind of like the idea of adding:

var hasWrongVarCase = !equal && same(lower(vars1), lower(vars2));

So that we only return hasWrongVarCase and hasUnexpectedVars. This lets us simplify the logic a little in compare.ts, and makes this code easier to read. I'd honestly prefer the name of the function to be clearer too, given the increased complexity, to something like verifyVars instead of sameVars.

Personally, that feels clearer to me. However, I'm not sure if we want to be making that many changes to this code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... you know what? Yolo :P I can always revert the next commit if we don't like it.

...options,
};

// TODO(CP-1614): Figure out how to make these messages translatable
Copy link
Contributor Author

@SonicScrewdriver SonicScrewdriver Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ticket was closed as "WONT DO" a long time ago, so I figured it was safe to clean up the TODO. I do wonder if we should make a new ticket, however.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant