From 53d4f33037585a0733ab33cfa259ea0d7bd3ab7d Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Wed, 4 Dec 2024 09:19:31 -0800 Subject: [PATCH 1/4] Move group scoring into group scorer --- .../src/components/graph-settings.tsx | 6 ++-- packages/perseus/src/renderer-util.ts | 26 ++++------------- packages/perseus/src/validation.types.ts | 1 + packages/perseus/src/widgets/group/group.tsx | 5 ++++ .../perseus/src/widgets/group/score-group.ts | 28 +++++++++++++++++++ 5 files changed, 42 insertions(+), 24 deletions(-) create mode 100644 packages/perseus/src/widgets/group/score-group.ts diff --git a/packages/perseus-editor/src/components/graph-settings.tsx b/packages/perseus-editor/src/components/graph-settings.tsx index c7ceda7499..a851d3f148 100644 --- a/packages/perseus-editor/src/components/graph-settings.tsx +++ b/packages/perseus-editor/src/components/graph-settings.tsx @@ -160,7 +160,6 @@ const GraphSettings = createReactClass({ // @ts-expect-error - TS2531 - Object is possibly 'null'. | TS2339 - Property 'value' does not exist on type 'Element | Text'. const url = ReactDOM.findDOMNode(this.refs["bg-url"]).value; // eslint-disable-line react/no-string-refs - url; // ? if (url) { Util.getImageSize(url, (width, height) => { if (this._isMounted) { @@ -561,9 +560,8 @@ const GraphSettings = createReactClass({ />

- Create an image in graphie, or use the - "Add image" function to create a - background. + Create an image in graphie, or use the "Add + image" function to create a background.

diff --git a/packages/perseus/src/renderer-util.ts b/packages/perseus/src/renderer-util.ts index cc332f8713..a0410701b6 100644 --- a/packages/perseus/src/renderer-util.ts +++ b/packages/perseus/src/renderer-util.ts @@ -53,27 +53,13 @@ export function emptyWidgetsFunctional( return false; } - let score: PerseusScore | null = null; - const userInput = userInputMap[id]; const scorer = getWidgetScorer(widget.type); - - if (widget.type === "group") { - const scores = scoreWidgetsFunctional( - widget.options.widgets, - Object.keys(widget.options.widgets), - userInputMap[id] as UserInputMap, - strings, - locale, - ); - score = Util.flattenScores(scores); - } else if (scorer) { - score = scorer( - userInput as UserInput, - widget.options, - strings, - locale, - ); - } + const score = scorer?.( + userInputMap[id] as UserInput, + widget.options, + strings, + locale, + ); if (score) { return Util.scoreIsEmpty(score); diff --git a/packages/perseus/src/validation.types.ts b/packages/perseus/src/validation.types.ts index 3f92fe36a8..cdb76f0150 100644 --- a/packages/perseus/src/validation.types.ts +++ b/packages/perseus/src/validation.types.ts @@ -91,6 +91,7 @@ export type PerseusExpressionRubric = { export type PerseusExpressionUserInput = string; export type PerseusGroupRubric = PerseusGroupWidgetOptions; +export type PerseusGroupUserInput = UserInputMap; export type PerseusGradedGroupRubric = PerseusGradedGroupWidgetOptions; diff --git a/packages/perseus/src/widgets/group/group.tsx b/packages/perseus/src/widgets/group/group.tsx index 6df7646007..ec5ae760d0 100644 --- a/packages/perseus/src/widgets/group/group.tsx +++ b/packages/perseus/src/widgets/group/group.tsx @@ -8,6 +8,8 @@ import {ApiOptions} from "../../perseus-api"; import Renderer from "../../renderer"; import {getPromptJSON as _getPromptJSON} from "../../widget-ai-utils/group/group-ai-utils"; +import scoreGroup from "./score-group"; + import type {PerseusGroupWidgetOptions} from "../../perseus-types"; import type { APIOptions, @@ -202,6 +204,9 @@ export default { displayName: "Group (SAT only)", widget: Group, traverseChildWidgets: traverseChildWidgets, + // TODO(LEMS-2656): remove TS suppression + // @ts-expect-error: Type 'UserInput' is not assignable to type 'PerseusCSProgramUserInput'. + scorer: scoreGroup, hidden: true, isLintable: true, } satisfies WidgetExports; diff --git a/packages/perseus/src/widgets/group/score-group.ts b/packages/perseus/src/widgets/group/score-group.ts new file mode 100644 index 0000000000..049c064b78 --- /dev/null +++ b/packages/perseus/src/widgets/group/score-group.ts @@ -0,0 +1,28 @@ +import {scoreWidgetsFunctional} from "../../renderer-util"; +import Util from "../../util"; + +import type {PerseusStrings} from "../../strings"; +import type {PerseusScore} from "../../types"; +import type { + PerseusGroupRubric, + PerseusGroupUserInput, +} from "../../validation.types"; + +function scoreGroup( + userInput: PerseusGroupUserInput, + options: PerseusGroupRubric, + strings: PerseusStrings, + locale: string, +): PerseusScore { + const scores = scoreWidgetsFunctional( + options.widgets, + Object.keys(options.widgets), + userInput, + strings, + locale, + ); + + return Util.flattenScores(scores); +} + +export default scoreGroup; From 09aa7056c5d9a4d65e209f489e1139516981043b Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Wed, 4 Dec 2024 10:46:07 -0800 Subject: [PATCH 2/4] Changeset and cleanup --- .changeset/metal-readers-impress.md | 5 +++++ .changeset/stupid-apricots-retire.md | 5 +++++ packages/perseus-editor/src/components/graph-settings.tsx | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .changeset/metal-readers-impress.md create mode 100644 .changeset/stupid-apricots-retire.md diff --git a/.changeset/metal-readers-impress.md b/.changeset/metal-readers-impress.md new file mode 100644 index 0000000000..5303398c8f --- /dev/null +++ b/.changeset/metal-readers-impress.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": patch +--- + +Refactor scoring for `group` widget to follow the same pattern as all other widgets diff --git a/.changeset/stupid-apricots-retire.md b/.changeset/stupid-apricots-retire.md new file mode 100644 index 0000000000..5011192a2e --- /dev/null +++ b/.changeset/stupid-apricots-retire.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus-editor": patch +--- + +Remove debugging call in GraphSettings component diff --git a/packages/perseus-editor/src/components/graph-settings.tsx b/packages/perseus-editor/src/components/graph-settings.tsx index a851d3f148..483033dba5 100644 --- a/packages/perseus-editor/src/components/graph-settings.tsx +++ b/packages/perseus-editor/src/components/graph-settings.tsx @@ -560,8 +560,9 @@ const GraphSettings = createReactClass({ />

- Create an image in graphie, or use the "Add - image" function to create a background. + Create an image in graphie, or use the + "Add image" function to create a + background.

From 9c6911bd62f24b9d81bde2544208ee3b02cb3557 Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Wed, 4 Dec 2024 15:28:27 -0800 Subject: [PATCH 3/4] Remove special case for 'group' in scorer also! :facepalm: --- packages/perseus/src/renderer-util.ts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/perseus/src/renderer-util.ts b/packages/perseus/src/renderer-util.ts index a0410701b6..065e68af95 100644 --- a/packages/perseus/src/renderer-util.ts +++ b/packages/perseus/src/renderer-util.ts @@ -119,22 +119,14 @@ export function scoreWidgetsFunctional( const userInput = userInputMap[id]; const scorer = getWidgetScorer(widget.type); - if (widget.type === "group") { - const scores = scoreWidgetsFunctional( - widget.options.widgets, - getWidgetIdsFromContent(widget.options.content), - userInputMap[id] as UserInputMap, - strings, - locale, - ); - widgetScores[id] = Util.flattenScores(scores); - } else if (scorer) { - widgetScores[id] = scorer( - userInput as UserInput, - widget.options, - strings, - locale, - ); + const score = scorer?.( + userInput as UserInput, + widget.options, + strings, + locale, + ); + if (score != null) { + widgetScores[id] = score; } }); From 581f83d23e144e0943ad06b315f871b0ebea4c98 Mon Sep 17 00:00:00 2001 From: Jeremy Wiebe Date: Wed, 4 Dec 2024 15:30:53 -0800 Subject: [PATCH 4/4] Comments --- packages/perseus/src/widgets/group/score-group.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/perseus/src/widgets/group/score-group.ts b/packages/perseus/src/widgets/group/score-group.ts index 049c064b78..4db4058118 100644 --- a/packages/perseus/src/widgets/group/score-group.ts +++ b/packages/perseus/src/widgets/group/score-group.ts @@ -8,6 +8,8 @@ import type { PerseusGroupUserInput, } from "../../validation.types"; +// The `group` widget is basically a widget hosting a full Perseus system in +// it. As such, scoring a group means scoring all widgets it contains. function scoreGroup( userInput: PerseusGroupUserInput, options: PerseusGroupRubric,