Skip to content

Commit

Permalink
Improve Grapher types (#1730)
Browse files Browse the repository at this point in the history
## Summary:
As part of the Server Side Scoring project, this refines Grapher's Rubric to be only what is needed for scoring. It also refines the UserInput type to refer to the rubric as the types are mostly the same. In addition, it cleans up some error expects and some related TODOs by adding lots more typing.

Issue: LEMS-2466

## Test plan:
- Confirm all tests pass
- Confirm widget works as intended via Storybook

Author: Myranae

Reviewers: Myranae, handeyeco

Required Reviewers:

Approved By: handeyeco

Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ gerald

Pull Request URL: #1730
  • Loading branch information
Myranae authored Oct 15, 2024
1 parent 43d3924 commit 2cc20b3
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 187 deletions.
5 changes: 5 additions & 0 deletions .changeset/wet-eyes-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus": patch
---

Refine Grapher types and clean up relevant code
100 changes: 51 additions & 49 deletions packages/perseus/src/perseus-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,56 @@ export type GraphRange = [
y: [min: number, max: number],
];

export type GrapherAnswerTypes =
| {
type: "absolute_value";
coords: [
// The vertex
Coord, // A point along one line of the absolute value "V" lines
Coord,
];
}
| {
type: "exponential";
// Two points along the asymptote line. Usually (always?) a
// horizontal or vertical line.
asymptote: [Coord, Coord];
// Two points along the exponential curve. One end of the curve
// trends towards the asymptote.
coords: [Coord, Coord];
}
| {
type: "linear";
// Two points along the straight line
coords: [Coord, Coord];
}
| {
type: "logarithm";
// Two points along the asymptote line.
asymptote: [Coord, Coord];
// Two points along the logarithmic curve. One end of the curve
// trends towards the asymptote.
coords: [Coord, Coord];
}
| {
type: "quadratic";
coords: [
// The vertex of the parabola
Coord, // A point along the parabola
Coord,
];
}
| {
type: "sinusoid";
// Two points on the same slope in the sinusoid wave line.
coords: [Coord, Coord];
}
| {
type: "tangent";
// Two points on the same slope in the tangent wave line.
coords: [Coord, Coord];
};

export type PerseusGrapherWidgetOptions = {
availableTypes: ReadonlyArray<
| "absolute_value"
Expand All @@ -484,55 +534,7 @@ export type PerseusGrapherWidgetOptions = {
| "sinusoid"
| "tangent"
>;
correct:
| {
type: "absolute_value";
coords: [
// The vertex
Coord, // A point along one line of the absolute value "V" lines
Coord,
];
}
| {
type: "exponential";
// Two points along the asymptote line. Usually (always?) a
// horizontal or vertical line.
asymptote: [Coord, Coord];
// Two points along the exponential curve. One end of the curve
// trends towards the asymptote.
coords: [Coord, Coord];
}
| {
type: "linear";
// Two points along the straight line
coords: [Coord, Coord];
}
| {
type: "logarithm";
// Two points along the asymptote line.
asymptote: [Coord, Coord];
// Two points along the logarithmic curve. One end of the curve
// trends towards the asymptote.
coords: [Coord, Coord];
}
| {
type: "quadratic";
coords: [
// The vertex of the parabola
Coord, // A point along the parabola
Coord,
];
}
| {
type: "sinusoid";
// Two points on the same slope in the sinusoid wave line.
coords: [Coord, Coord];
}
| {
type: "tangent";
// Two points on the same slope in the tangent wave line.
coords: [Coord, Coord];
};
correct: GrapherAnswerTypes;
graph: {
backgroundImage: {
bottom?: number;
Expand Down
17 changes: 5 additions & 12 deletions packages/perseus/src/validation.types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type {Coord} from "./interactive2/types";
import type {
GrapherAnswerTypes,
PerseusDefinitionWidgetOptions,
PerseusDropdownChoice,
PerseusExplanationWidgetOptions,
PerseusExpressionAnswerForm,
PerseusGradedGroupSetWidgetOptions,
PerseusGradedGroupWidgetOptions,
PerseusGrapherWidgetOptions,
PerseusGraphType,
PerseusGroupWidgetOptions,
PerseusIFrameWidgetOptions,
Expand Down Expand Up @@ -79,18 +78,12 @@ export type PerseusGradedGroupRubric = PerseusGradedGroupWidgetOptions;

export type PerseusGradedGroupSetRubric = PerseusGradedGroupSetWidgetOptions;

export type PerseusGrapherRubric = PerseusGrapherWidgetOptions;

/**
* TODO: this is kind of just a guess right now
* based off of an old comment in grapher
*/
export type PerseusGrapherUserInput = {
type: string;
asymptote: ReadonlyArray<Coord>;
coords: ReadonlyArray<Coord>;
export type PerseusGrapherRubric = {
correct: GrapherAnswerTypes;
};

export type PerseusGrapherUserInput = PerseusGrapherRubric["correct"];

export type PerseusIFrameRubric = PerseusIFrameWidgetOptions;

export type PerseusIFrameUserInput = {
Expand Down
78 changes: 78 additions & 0 deletions packages/perseus/src/widgets/grapher/grapher-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type {Coord} from "@khanacademy/perseus";

export type Coords = [Coord, Coord];

// Includes common properties for all function types and plotDefaults
type SharedGrapherType = {
url: string;
defaultCoords: Coords;
getFunctionForCoeffs: (coeffs: ReadonlyArray<number>, x: number) => number;
getEquationString: (coords: Coords, asymptote?: Coords) => string | null;
areEqual: (
coeffs1: ReadonlyArray<number>,
coeffs2: ReadonlyArray<number>,
) => boolean;
Movable: any;
getCoefficients: (
coords: Coords,
asymptote?: Coords,
) => ReadonlyArray<number> | undefined;
};

type AsymptoticGraphsType = {
defaultAsymptote: Coords;
extraCoordConstraint: (
newCoord: Coord,
oldCoord: Coord,
coords: Coords,
asymptote: Coords,
graph: any,
) => boolean | Coord;
extraAsymptoteConstraint: (
newCoord: Coord,
oldCoord: Coord,
coords: Coords,
asymptote: Coords,
graph: any,
) => Coord;
allowReflectOverAsymptote: boolean;
};

export type LinearType = SharedGrapherType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {fn: any};
};

export type QuadraticType = SharedGrapherType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {
a: number;
b: number;
c: number;
};
};

export type SinusoidType = SharedGrapherType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {
a: number;
b: number;
c: number;
d: number;
};
};

export type TangentType = SharedGrapherType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {fn: any};
};

export type ExponentialType = SharedGrapherType &
AsymptoticGraphsType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {fn: any};
};

export type LogarithmType = SharedGrapherType &
AsymptoticGraphsType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {fn: any};
};

export type AbsoluteValueType = SharedGrapherType & {
getPropsForCoeffs: (coeffs: ReadonlyArray<number>) => {fn: any};
};
38 changes: 0 additions & 38 deletions packages/perseus/src/widgets/grapher/grapher-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,11 @@ describe("grapherValidator", () => {
};

const rubric: PerseusGrapherRubric = {
availableTypes: ["exponential", "logarithm"],
correct: {
type: "logarithm",
asymptote,
coords,
},
// The rubric type is probably wrong,
// the validator doesn't use graph
graph: {} as any,
};

// Act
Expand Down Expand Up @@ -64,15 +60,11 @@ describe("grapherValidator", () => {
};

const rubric: PerseusGrapherRubric = {
availableTypes: ["exponential", "logarithm"],
correct: {
type: "exponential",
asymptote,
coords,
},
// The rubric type is probably wrong,
// the validator doesn't use graph
graph: {} as any,
};

// Act
Expand All @@ -86,10 +78,6 @@ describe("grapherValidator", () => {
// I honestly don't understand what a coefficient is
// but this seems to get triggered when the type is "linear"
// and the points are in the same spot
const asymptote: [Coord, Coord] = [
[-10, -10],
[-10, -10],
];
const coords: [Coord, Coord] = [
[-10, -10],
[-10, -10],
Expand All @@ -98,19 +86,14 @@ describe("grapherValidator", () => {
// Arrange
const userInput: PerseusGrapherUserInput = {
type: "linear",
asymptote,
coords,
};

const rubric: PerseusGrapherRubric = {
availableTypes: ["linear"],
correct: {
type: "linear",
coords,
},
// The rubric type is probably wrong,
// the validator doesn't use graph
graph: {} as any,
};

// Act
Expand All @@ -121,10 +104,6 @@ describe("grapherValidator", () => {
});

it("can be answered correctly", () => {
const asymptote: [Coord, Coord] = [
[-10, -10],
[10, 10],
];
const coords: [Coord, Coord] = [
[-10, -10],
[10, 10],
Expand All @@ -133,19 +112,14 @@ describe("grapherValidator", () => {
// Arrange
const userInput: PerseusGrapherUserInput = {
type: "linear",
asymptote,
coords,
};

const rubric: PerseusGrapherRubric = {
availableTypes: ["linear"],
correct: {
type: "linear",
coords,
},
// The rubric type is probably wrong,
// the validator doesn't use graph
graph: {} as any,
};

// Act
Expand All @@ -156,35 +130,23 @@ describe("grapherValidator", () => {
});

it("can be answered incorrectly when user input and rubric coords don't match", () => {
// TODO: user input type is probably wrong,
// I don't think asymptote is needed for all types
const asymptote: [Coord, Coord] = [
[10, 10],
[-10, -10],
];

// Arrange
const userInput: PerseusGrapherUserInput = {
type: "linear",
asymptote,
coords: [
[2, 3],
[-4, -5],
],
};

const rubric: PerseusGrapherRubric = {
availableTypes: ["linear"],
correct: {
type: "linear",
coords: [
[-10, -10],
[10, 10],
],
},
// The rubric type is probably wrong,
// the validator doesn't use graph
graph: {} as any,
};

// Act
Expand Down
Loading

0 comments on commit 2cc20b3

Please sign in to comment.