Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move main Scorer and Validator to PerseusScore #2165

Merged
merged 28 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8aa4028
[LEMS-2737/move-scoring-logic] WIP: start the move
handeyeco Jan 28, 2025
b25fb6c
[LEMS-2737/move-scoring-logic] WIP: scoring registry
handeyeco Jan 28, 2025
d2387fc
[LEMS-2737/move-scoring-logic] WIP: handle noop scorer
handeyeco Jan 28, 2025
3523c8f
[LEMS-2737/move-scoring-logic] WIP: move group scorer
handeyeco Jan 28, 2025
8fc194e
[LEMS-2737/move-scoring-logic] WIP: move alignments
handeyeco Jan 28, 2025
15c03e5
[LEMS-2737/move-scoring-logic] WIP: Perseus Core registry
handeyeco Jan 28, 2025
39efebe
[LEMS-2737/move-scoring-logic] WIP: getSupportedAlignments
handeyeco Jan 28, 2025
0934f34
[LEMS-2737/move-scoring-logic] WIP: add registry helpers
handeyeco Jan 28, 2025
f764d86
[LEMS-2737/move-scoring-logic] WIP: mock widget
handeyeco Jan 28, 2025
5348013
[LEMS-2737/move-scoring-logic] WIP: lint/tsc happy, tests sad
handeyeco Jan 28, 2025
14450db
[LEMS-2737/move-scoring-logic] WIP: fix some tests
handeyeco Jan 28, 2025
38ea7b6
[LEMS-2737/move-scoring-logic] fix tests
handeyeco Jan 28, 2025
de0e4ae
[LEMS-2737/move-scoring-logic] convert Log to Error
handeyeco Jan 28, 2025
e894520
[LEMS-2737/move-scoring-logic] remove validation checks in scorers
handeyeco Jan 28, 2025
7d73db2
[LEMS-2737/move-scoring-logic] fix test util file placement
handeyeco Jan 28, 2025
f231ad4
[LEMS-2737/move-scoring-logic] docs(changeset): Move scorePerseusItem…
handeyeco Jan 28, 2025
4216e8a
[LEMS-2737/move-scoring-logic] more cleanup
handeyeco Jan 29, 2025
d7f2607
[LEMS-2737/move-scoring-logic] fix conflicts
handeyeco Jan 30, 2025
83080a4
[LEMS-2737/move-scoring-logic] add grapher to core registry
handeyeco Jan 30, 2025
34055a0
[LEMS-2737/move-scoring-logic] rename WidgetLogic to CoreWidgetRegistry
handeyeco Jan 30, 2025
19a5d84
[LEMS-2737/move-scoring-logic] add oldWidgetInfo to error metadata
handeyeco Jan 30, 2025
d9a6699
[LEMS-2737/move-scoring-logic] secure getSupportedAlignments a little
handeyeco Jan 30, 2025
488f663
[LEMS-2737/move-scoring-logic] remove underscore extends
handeyeco Jan 30, 2025
a916f59
[LEMS-2737/move-scoring-logic] cleanup getSupportedAlignments more
handeyeco Jan 30, 2025
852109c
[LEMS-2737/move-scoring-logic] cleanup getDefaultAlignment
handeyeco Jan 30, 2025
8fed47e
[LEMS-2737/move-scoring-logic] merge main, resolve conflicts
handeyeco Feb 3, 2025
47569f0
[LEMS-2737/move-scoring-logic] fix conflicts
handeyeco Feb 3, 2025
de42db3
[LEMS-2737/move-scoring-logic] restore external API
handeyeco Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/wise-owls-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@khanacademy/perseus": major
"@khanacademy/perseus-core": minor
"@khanacademy/perseus-score": minor
"@khanacademy/perseus-dev-ui": patch
"@khanacademy/perseus-editor": patch
---

Move scorePerseusItem logic to PerseusScore
3 changes: 1 addition & 2 deletions dev/flipbook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import {useEffect, useMemo, useReducer, useRef, useState} from "react";

import {Renderer} from "../packages/perseus/src";
import {SvgImage} from "../packages/perseus/src/components";
import {scorePerseusItem} from "../packages/perseus/src/renderer-util";
import {mockStrings} from "../packages/perseus/src/strings";
import {isCorrect} from "../packages/perseus/src/util/scoring";
import {trueForAllMafsSupportedGraphTypes} from "../packages/perseus/src/widgets/interactive-graphs/mafs-supported-graph-types";
import {scorePerseusItem} from "../packages/perseus-score/src";

import {EditableControlledInput} from "./editable-controlled-input";
import {
Expand Down Expand Up @@ -324,7 +324,6 @@ function GradableRenderer(props: QuestionRendererProps) {
const score = scorePerseusItem(
question,
rendererRef.current.getUserInputMap(),
mockStrings,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now all validators and scorers should be sending error codes instead of error messages, so we don't need strings anymore.

"en",
);
setScore(score);
Expand Down
8 changes: 8 additions & 0 deletions packages/perseus-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type {
MarkerType,
InteractiveMarkerType,
Relationship,
Alignment,
} from "./types";
export type {ErrorKind} from "./error/errors";
export type {FunctionTypeMappingKeys} from "./utils/grapher-util";
Expand Down Expand Up @@ -112,8 +113,15 @@ export type {TableDefaultWidgetOptions} from "./widgets/table";
export {default as videoLogic} from "./widgets/video";
export type {VideoDefaultWidgetOptions} from "./widgets/video";

export {
getUpgradedWidgetOptions,
upgradeWidgetInfoToLatestVersion,
} from "./widgets/upgrade";

export type * from "./widgets/logic-export.types";

export * as CoreWidgetRegistry from "./widgets/core-widget-registry";

export {default as getOrdererPublicWidgetOptions} from "./widgets/orderer/orderer-util";
export {default as getCategorizerPublicWidgetOptions} from "./widgets/categorizer/categorizer-util";
export {default as getCSProgramPublicWidgetOptions} from "./widgets/cs-program/cs-program-util";
Expand Down
9 changes: 9 additions & 0 deletions packages/perseus-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ export type InteractiveMarkerType = MarkerType & {
// Used for NumberLine
// TODO: can this be merged with PerseusNumberLineWidgetOptions.correctRel?
export type Relationship = "lt" | "gt" | "le" | "ge";

export type Alignment =
| "default"
| "block"
| "inline-block"
| "inline"
| "float-left"
| "float-right"
| "full-width";
135 changes: 135 additions & 0 deletions packages/perseus-core/src/widgets/core-widget-registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import categorizerWidgetLogic from "./categorizer";
import csProgramWidgetLogic from "./cs-program";
import definitionWidgetLogic from "./definition";
import dropdownWidgetLogic from "./dropdown";
import explanationWidgetLogic from "./explanation";
import expressionWidgetLogic from "./expression";
import gradedGroupWidgetLogic from "./graded-group";
import gradedGroupSetWidgetLogic from "./graded-group-set";
import grapherWidgetLogic from "./grapher";
import groupWidgetLogic from "./group";
import iframeWidgetLogic from "./iframe";
import imageWidgetLogic from "./image";
import inputNumberWidgetLogic from "./input-number";
import interactionWidgetLogic from "./interaction";
import interactiveGraphWidgetLogic from "./interactive-graph";
import labelImageWidgetLogic from "./label-image";
import matcherWidgetLogic from "./matcher";
import matrixWidgetLogic from "./matrix";
import measurerWidgetLogic from "./measurer";
import numberLineWidgetLogic from "./number-line";
import numericInputWidgetLogic from "./numeric-input";
import ordererWidgetLogic from "./orderer";
import passageWidgetLogic from "./passage";
import passageRefWidgetLogic from "./passage-ref";
import passageRefTargetWidgetLogic from "./passage-ref-target";
import phetSimulationWidgetLogic from "./phet-simulation";
import plotterWidgetLogic from "./plotter";
import pythonProgramWidgetLogic from "./python-program";
import radioWidgetLogic from "./radio";
import sorterWidgetLogic from "./sorter";
import tableWidgetLogic from "./table";
import videoWidgetLogic from "./video";

import type {WidgetLogic} from "./logic-export.types";
import type {Alignment} from "../types";

const widgets = {};

function registerWidget(type: string, logic: WidgetLogic) {
widgets[type] = logic;
}

export function isWidgetRegistered(type: string) {
const widgetLogic = widgets[type];
return !!widgetLogic;
}

export function getCurrentVersion(type: string) {
const widgetLogic = widgets[type];
return widgetLogic?.version || {major: 0, minor: 0};
}

export function getWidgetOptionsUpgrades(type: string) {
const widgetLogic = widgets[type];
return widgetLogic?.widgetOptionsUpgrades || {};
}

export function getDefaultWidgetOptions(type: string) {
const widgetLogic = widgets[type];
return widgetLogic?.defaultWidgetOptions || {};
}

/**
* Handling for the optional alignments for widgets
* See widget-container.jsx for details on how alignments are implemented.
*/

/**
* Returns the list of supported alignments for the given (string) widget
* type. This is used primarily at editing time to display the choices
* for the user.
*
* Supported alignments are given as an array of strings in the exports of
* a widget's module.
*/
export const getSupportedAlignments = (
type: string,
): ReadonlyArray<Alignment> => {
const widgetLogic = widgets[type];
if (!widgetLogic?.supportedAlignments?.[0]) {
// default alignments
return ["default"];
}
return widgetLogic?.supportedAlignments;
};

/**
* For the given (string) widget type, determine the default alignment for
* the widget. This is used at rendering time to go from "default" alignment
* to the actual alignment displayed on the screen.
*
* The default alignment is given either as a string (called
* `defaultAlignment`) or a function (called `getDefaultAlignment`) on
* the exports of a widget's module.
*/
export const getDefaultAlignment = (type: string): Alignment => {
const widgetLogic = widgets[type];
if (!widgetLogic?.defaultAlignment) {
return "block";
}
return widgetLogic.defaultAlignment;
};

registerWidget("categorizer", categorizerWidgetLogic);
registerWidget("cs-program", csProgramWidgetLogic);
registerWidget("definition", definitionWidgetLogic);
registerWidget("dropdown", dropdownWidgetLogic);
registerWidget("explanation", explanationWidgetLogic);
registerWidget("expression", expressionWidgetLogic);
registerWidget("graded-group", gradedGroupWidgetLogic);
registerWidget("graded-group-set", gradedGroupSetWidgetLogic);
registerWidget("grapher", grapherWidgetLogic);
registerWidget("group", groupWidgetLogic);
registerWidget("iframe", iframeWidgetLogic);
registerWidget("image", imageWidgetLogic);
registerWidget("input-number", inputNumberWidgetLogic);
registerWidget("interaction", interactionWidgetLogic);
registerWidget("interactive-graph", interactiveGraphWidgetLogic);
registerWidget("label-image", labelImageWidgetLogic);
registerWidget("matcher", matcherWidgetLogic);
registerWidget("matrix", matrixWidgetLogic);
registerWidget("measurer", measurerWidgetLogic);
registerWidget("number-line", numberLineWidgetLogic);
registerWidget("numeric-input", numericInputWidgetLogic);
registerWidget("orderer", ordererWidgetLogic);
registerWidget("passage", passageWidgetLogic);
registerWidget("passage-ref", passageRefWidgetLogic);
registerWidget("passage-ref-target", passageRefTargetWidgetLogic);
registerWidget("phet-simulation", phetSimulationWidgetLogic);
registerWidget("plotter", plotterWidgetLogic);
registerWidget("python-program", pythonProgramWidgetLogic);
registerWidget("radio", radioWidgetLogic);
registerWidget("sorter", sorterWidgetLogic);
registerWidget("table", tableWidgetLogic);
registerWidget("video", videoWidgetLogic);
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/cs-program/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultWidgetOptions: CSProgramDefaultWidgetOptions = {
const csProgramWidgetLogic: WidgetLogic = {
name: "cs-program",
defaultWidgetOptions,
supportedAlignments: ["block", "full-width"],
};

export default csProgramWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/definition/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const defaultWidgetOptions: DefinitionDefaultWidgetOptions = {
const definitionWidgetLogic: WidgetLogic = {
name: "definition",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default definitionWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/dropdown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const defaultWidgetOptions: DropdownDefaultWidgetOptions = {
const dropdownWidgetLogic: WidgetLogic = {
name: "definition",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default dropdownWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/explanation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const defaultWidgetOptions: ExplanationDefaultWidgetOptions = {
const explanationWidgetLogic: WidgetLogic = {
name: "explanation",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default explanationWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/expression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const expressionWidgetLogic: WidgetLogic = {
version: currentVersion,
widgetOptionsUpgrades: widgetOptionsUpgrades,
defaultWidgetOptions: defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default expressionWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/graded-group-set/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const defaultWidgetOptions: GradedGroupSetDefaultWidgetOptions = {
gradedGroups: [],
};

const GradedGroupSetWidgetLogic: WidgetLogic = {
const gradedGroupSetWidgetLogic: WidgetLogic = {
name: "graded-group-set",
defaultWidgetOptions,
};

export default GradedGroupSetWidgetLogic;
export default gradedGroupSetWidgetLogic;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This were just mistakes from previous PRs.

4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/graded-group/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const defaultWidgetOptions: GradedGroupDefaultWidgetOptions = {
hint: null,
};

const GradedGroupWidgetLogic: WidgetLogic = {
const gradedGroupWidgetLogic: WidgetLogic = {
name: "graded-group",
defaultWidgetOptions,
};

export default GradedGroupWidgetLogic;
export default gradedGroupWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/group/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const defaultWidgetOptions: GroupDefaultWidgetOptions = {
metadata: undefined,
};

const GroupWidgetLogic: WidgetLogic = {
const groupWidgetLogic: WidgetLogic = {
name: "group",
defaultWidgetOptions,
};

export default GroupWidgetLogic;
export default groupWidgetLogic;
2 changes: 2 additions & 0 deletions packages/perseus-core/src/widgets/image/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const defaultWidgetOptions: ImageDefaultWidgetOptions = {
const imageWidgetLogic: WidgetLogic = {
name: "image",
defaultWidgetOptions,
supportedAlignments: ["block", "full-width"],
defaultAlignment: "block",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alignment is used during the upgrade process, that's why I moved all of these.

};

export default imageWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/input-number/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const defaultWidgetOptions: InputNumberDefaultWidgetOptions = {
const inputNumberWidgetLogic: WidgetLogic = {
name: "input-number",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default inputNumberWidgetLogic;
3 changes: 3 additions & 0 deletions packages/perseus-core/src/widgets/logic-export.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {Version} from "../data-schema";
import type {Alignment} from "../types";

export type WidgetOptionsUpgradeMap = {
// OldProps => NewProps,
Expand All @@ -10,4 +11,6 @@ export type WidgetLogic = {
version?: Version;
widgetOptionsUpgrades?: WidgetOptionsUpgradeMap;
defaultWidgetOptions?: any;
supportedAlignments?: ReadonlyArray<Alignment>;
defaultAlignment?: Alignment;
};
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/numeric-input/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const defaultWidgetOptions: NumericInputDefaultWidgetOptions = {
const numericInputWidgetLogic: WidgetLogic = {
name: "numeric-input",
defaultWidgetOptions,
defaultAlignment: "inline-block",
};

export default numericInputWidgetLogic;
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const defaultWidgetOptions: PassageRefTargetDefaultWidgetOptions = {
const passageRefTargetWidgetLogic: WidgetLogic = {
name: "passageRefTarget",
defaultWidgetOptions,
defaultAlignment: "inline",
};

export default passageRefTargetWidgetLogic;
1 change: 1 addition & 0 deletions packages/perseus-core/src/widgets/passage-ref/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const passageRefWidgetLogic: WidgetLogic = {
name: "passageRef",
version: currentVersion,
defaultWidgetOptions: defaultWidgetOptions,
defaultAlignment: "inline",
};

export default passageRefWidgetLogic;
4 changes: 2 additions & 2 deletions packages/perseus-core/src/widgets/phet-simulation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ const defaultWidgetOptions: PhetSimulationDefaultWidgetOptions = {
description: "",
};

const PhetSimulationWidgetLogic: WidgetLogic = {
const phetSimulationWidgetLogic: WidgetLogic = {
name: "phet-simulation",
defaultWidgetOptions,
};

export default PhetSimulationWidgetLogic;
export default phetSimulationWidgetLogic;
Loading