Skip to content

Commit

Permalink
[UnlimitedPolygon] Fix open polygon scoring issues. (#1999)
Browse files Browse the repository at this point in the history
## Summary:
This PR fixes and adds 3 things to the Unlimited Polygon Experience:

1. Only closed unlimited polygons are scorable.
2. Correct Unlimited Polygons in our editor are closed when rendered (i.e. unlimited polygons that are rendered with exisitng coordinates of 3 or more are closed at start).
3. Added save warnings to editor to notify content creators to close their unlimited polygons before saving.

Issue: LEMS-2682

## Test plan:

1. Go to http://localhost:6006/?path=/story/perseuseditor-widgets-interactive-graph--interactive-graph-unlimited-polygon.
2. Notice that the unlimited polygon correct answer is automatically closed on render.
3. Go to http://localhost:6006/?path=/story/perseus-widgets-interactive-graph--unlimited-polygon-with-mafs
4. Draw a polygon and check it when it's open, you should see the score is type `invalid`
5. Close the polygon and git it again, it should be a `valid` score.

Author: catandthemachines

Reviewers: nishasy, anakaren-rojas

Required Reviewers:

Approved By: nishasy

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

Pull Request URL: #1999
  • Loading branch information
catandthemachines authored Dec 16, 2024
1 parent b09d19b commit 278527b
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changeset/weak-pandas-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": patch
"@khanacademy/perseus-editor": patch
---

Fixing open polygon scoring issues within exercises and editors.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
segmentWithStartingCoordsQuestion,
segmentsWithStartingCoordsQuestion,
sinusoidWithStartingCoordsQuestion,
unlimitedPolygonWithStartingCoordsQuestion,
} from "../../../perseus/src/widgets/interactive-graphs/interactive-graph.testdata";
import {registerAllWidgetsAndEditorsForTesting} from "../util/register-all-widgets-and-editors-for-testing";

Expand Down Expand Up @@ -125,6 +126,14 @@ export const InteractiveGraphPolygon = (): React.ReactElement => {
);
};

export const InteractiveGraphUnlimitedPolygon = (): React.ReactElement => {
return (
<EditorPageWithStorybookPreview
question={unlimitedPolygonWithStartingCoordsQuestion}
/>
);
};

export const InteractiveGraphAngle = (): React.ReactElement => {
return (
<EditorPageWithStorybookPreview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,15 @@ class InteractiveGraphEditor extends React.Component<Props> {
}
}

// Do not save a unlimited polygon that is open (coords is null).
if (
this.props.graph?.type === "polygon" &&
this.props.graph.numSides === "unlimited" &&
this.props.graph.coords === null
) {
issues.push("Polygon must be closed.");
}

return issues;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ const PolygonGraph = (props: Props) => {
}
}, [props.graphState.focusedPointIndex, pointsRef]);

// If the unlimited polygon is rendered with 3 or more coordinates
// Close the polygon, but only on first render.
React.useEffect(() => {
if (numSides === "unlimited" && props.graphState.coords.length > 2) {
dispatch(actions.polygon.closePolygon());
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const statefulProps: StatefulProps = {
...props,
graphConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,19 @@ export const polygonWithStartingCoordsQuestion: PerseusRenderer =
})
.build();

export const unlimitedPolygonWithStartingCoordsQuestion: PerseusRenderer =
interactiveGraphQuestionBuilder()
.withPolygon("grid", {
numSides: "unlimited",
coords: [
[-4.5, -6],
[4.5, -5],
[3.5, 0.5],
[-4.5, 0],
],
})
.build();

export const polygonWithAnglesQuestion: PerseusRenderer =
interactiveGraphQuestionBuilder()
.withContent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@ const defaultAngleState: InteractiveGraphState = {
allowReflexAngles: false,
};

const defaultUnlimitedPolygonState: InteractiveGraphState = {
type: "polygon",
closedPolygon: false,
focusedPointIndex: 0,
coords: [[5, 0]],
numSides: "unlimited",
hasBeenInteractedWith: true,
showRemovePointButton: false,
showKeyboardInteractionInvitation: false,
interactionMode: "mouse",
range: [
[-10, 10],
[-10, 10],
],
snapStep: [1, 1],
snapTo: "grid",
showSides: true,
showAngles: true,
};

describe("getGradableGraph", () => {
/**
* Originally `getGradableGraph` was returning a PerseusGraphType with just a
Expand Down Expand Up @@ -117,4 +137,30 @@ describe("getGradableGraph", () => {
[-5, -5],
]);
});

it("returns null coordinates if the unlimited polygon graph is open", () => {
const state: InteractiveGraphState = {
...defaultUnlimitedPolygonState,
closedPolygon: false,
};
const initialGraph: PerseusGraphType = {
type: "polygon",
};
const result = getGradableGraph(state, initialGraph);
invariant(result.type === "polygon");
expect(result.coords).toEqual(null);
});

it("returns coordinates if the unlimited polygon graph is closed", () => {
const state: InteractiveGraphState = {
...defaultUnlimitedPolygonState,
closedPolygon: true,
};
const initialGraph: PerseusGraphType = {
type: "polygon",
};
const result = getGradableGraph(state, initialGraph);
invariant(result.type === "polygon");
expect(result.coords).toEqual([[5, 0]]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ export function getGradableGraph(
}

if (state.type === "polygon" && initialGraph.type === "polygon") {
// Unless the polygon is closed it is not considered score-able.
if (state.numSides === "unlimited" && !state.closedPolygon) {
return {
...initialGraph,
coords: null,
};
}

return {
...initialGraph,
coords: state.coords,
Expand Down

0 comments on commit 278527b

Please sign in to comment.