@khanacademy/perseus 36.1.0 → 36.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/index.js CHANGED
@@ -3157,13 +3157,13 @@ function eq$4(x, y) {
3157
3157
  * Deep approximate equality on primitives, numbers, arrays, and objects.
3158
3158
  * Recursive.
3159
3159
  */
3160
- function deepEq$5(x, y) {
3160
+ function deepEq$6(x, y) {
3161
3161
  if (Array.isArray(x) && Array.isArray(y)) {
3162
3162
  if (x.length !== y.length) {
3163
3163
  return false;
3164
3164
  }
3165
3165
  for (let i = 0; i < x.length; i++) {
3166
- if (!deepEq$5(x[i], y[i])) {
3166
+ if (!deepEq$6(x[i], y[i])) {
3167
3167
  return false;
3168
3168
  }
3169
3169
  }
@@ -3181,10 +3181,10 @@ function deepEq$5(x, y) {
3181
3181
  if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
3182
3182
  return x === y || _.all(x, function (v, k) {
3183
3183
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
3184
- return deepEq$5(y[k], v);
3184
+ return deepEq$6(y[k], v);
3185
3185
  }) && _.all(y, function (v, k) {
3186
3186
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
3187
- return deepEq$5(x[k], v);
3187
+ return deepEq$6(x[k], v);
3188
3188
  });
3189
3189
  }
3190
3190
  if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
@@ -3464,7 +3464,7 @@ const Util = {
3464
3464
  tickStepFromNumTicks,
3465
3465
  constrainedTickStepsFromTickSteps,
3466
3466
  eq: eq$4,
3467
- deepEq: deepEq$5,
3467
+ deepEq: deepEq$6,
3468
3468
  parseQueryString,
3469
3469
  updateQueryString: updateQueryString$2,
3470
3470
  strongEncodeURIComponent,
@@ -10786,7 +10786,7 @@ class WrappedLine extends WrappedDrawing {
10786
10786
  */
10787
10787
  const {
10788
10788
  eq: eq$3,
10789
- deepEq: deepEq$4
10789
+ deepEq: deepEq$5
10790
10790
  } = Util;
10791
10791
 
10792
10792
  // This should really be a readonly tuple of [number, number]
@@ -10946,7 +10946,7 @@ function similar(coords1, coords2, tolerance) {
10946
10946
  angles = rotate(angles, i);
10947
10947
  // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
10948
10948
  sides = rotate(sides, i);
10949
- if (deepEq$4(angles1, angles)) {
10949
+ if (deepEq$5(angles1, angles)) {
10950
10950
  const sidePairs = _.zip(sides1, sides);
10951
10951
  const factors = _.map(sidePairs, function (pair) {
10952
10952
  return pair[0] / pair[1];
@@ -13884,7 +13884,7 @@ _.extend(MovableAngle.prototype, {
13884
13884
 
13885
13885
  /* eslint-disable @babel/no-invalid-this */
13886
13886
  const nestedMap$1 = Util.nestedMap;
13887
- const deepEq$3 = Util.deepEq;
13887
+ const deepEq$4 = Util.deepEq;
13888
13888
 
13889
13889
  /**
13890
13890
  * A base class for all Graphie Movables
@@ -13981,7 +13981,7 @@ const createSimpleClass = function createSimpleClass(addFunction) {
13981
13981
  this._prevProps = this.props;
13982
13982
  },
13983
13983
  modify: function (graphie) {
13984
- if (!deepEq$3(this.props, this._prevProps)) {
13984
+ if (!deepEq$4(this.props, this._prevProps)) {
13985
13985
  this.remove();
13986
13986
  this.add(graphie);
13987
13987
  this._prevProps = this.props;
@@ -16684,7 +16684,7 @@ var Movables = {
16684
16684
  const GraphieMovable = GraphieClasses.GraphieMovable;
16685
16685
  const createGraphie = GraphUtils.createGraphie;
16686
16686
  const {
16687
- deepEq: deepEq$2,
16687
+ deepEq: deepEq$3,
16688
16688
  nestedMap
16689
16689
  } = Util;
16690
16690
  const {
@@ -16926,7 +16926,7 @@ class Graphie extends React.Component {
16926
16926
  if (this.props.setup !== prevProps.setup) {
16927
16927
  Log.error("<Graphie> was given a new setup function. " + "This is a bad idea; please refactor your code to give " + "the same setup function reference to <Graphie> on " + "every render.", Errors.Internal);
16928
16928
  }
16929
- if (!deepEq$2(this.props.options, prevProps.options) || !deepEq$2(this.props.box, prevProps.box) || !deepEq$2(this.props.range, prevProps.range)) {
16929
+ if (!deepEq$3(this.props.options, prevProps.options) || !deepEq$3(this.props.box, prevProps.box) || !deepEq$3(this.props.range, prevProps.range)) {
16930
16930
  this._setupGraphie();
16931
16931
  }
16932
16932
  this._updateMovables();
@@ -30988,10 +30988,16 @@ const shouldShowLabel = (currentTick, range, tickStep) => {
30988
30988
  function generateTickLocations(tickStep, min, max) {
30989
30989
  const ticks = [];
30990
30990
 
30991
+ // Calculate the number of significant decimals in the tick step so
30992
+ // that we can match the desired precision when generating ticks.
30993
+ const decimalSigFigs = countSignificantDecimals(tickStep);
30994
+
30991
30995
  // Add ticks in the positive direction
30992
30996
  const start = Math.max(min, 0);
30993
30997
  for (let _i = start + tickStep; _i < max; _i += tickStep) {
30994
- ticks.push(_i);
30998
+ // Match to the same number of decimal places as the tick step
30999
+ // to avoid floating point errors when working with small numbers
31000
+ ticks.push(parseFloat(_i.toFixed(decimalSigFigs)));
30995
31001
  }
30996
31002
 
30997
31003
  // Add ticks in the negative direction
@@ -31002,6 +31008,15 @@ function generateTickLocations(tickStep, min, max) {
31002
31008
  }
31003
31009
  return ticks;
31004
31010
  }
31011
+
31012
+ // Count the number of significant digits after the decimal point
31013
+ const countSignificantDecimals = number => {
31014
+ const numStr = number.toString();
31015
+ if (!numStr.includes(".")) {
31016
+ return 0;
31017
+ }
31018
+ return numStr.split(".")[1].length;
31019
+ };
31005
31020
  const AxisTicks = () => {
31006
31021
  const {
31007
31022
  tickStep,
@@ -35742,7 +35757,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
35742
35757
  });
35743
35758
 
35744
35759
  const eq$1 = Util.eq;
35745
- const deepEq$1 = Util.deepEq;
35760
+ const deepEq$2 = Util.deepEq;
35746
35761
  function interactiveGraphValidator(userInput, rubric) {
35747
35762
  // None-type graphs are not graded
35748
35763
  if (userInput.type === "none" && rubric.correct.type === "none") {
@@ -35798,7 +35813,7 @@ function interactiveGraphValidator(userInput, rubric) {
35798
35813
  const correctCoeffs = getQuadraticCoefficients(
35799
35814
  // @ts-expect-error - TS2345 - Argument of type 'readonly Coord[] | undefined' is not assignable to parameter of type 'readonly Coord[]'.
35800
35815
  rubric.correct.coords);
35801
- if (deepEq$1(guessCoeffs, correctCoeffs)) {
35816
+ if (deepEq$2(guessCoeffs, correctCoeffs)) {
35802
35817
  return {
35803
35818
  type: "points",
35804
35819
  earned: 1,
@@ -35814,7 +35829,7 @@ function interactiveGraphValidator(userInput, rubric) {
35814
35829
  const canonicalGuessCoeffs = canonicalSineCoefficients$1(guessCoeffs);
35815
35830
  const canonicalCorrectCoeffs = canonicalSineCoefficients$1(correctCoeffs);
35816
35831
  // If the canonical coefficients match, it's correct.
35817
- if (deepEq$1(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
35832
+ if (deepEq$2(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
35818
35833
  return {
35819
35834
  type: "points",
35820
35835
  earned: 1,
@@ -35823,7 +35838,7 @@ function interactiveGraphValidator(userInput, rubric) {
35823
35838
  };
35824
35839
  }
35825
35840
  } else if (userInput.type === "circle" && rubric.correct.type === "circle") {
35826
- if (deepEq$1(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
35841
+ if (deepEq$2(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
35827
35842
  return {
35828
35843
  type: "points",
35829
35844
  earned: 1,
@@ -35845,7 +35860,7 @@ function interactiveGraphValidator(userInput, rubric) {
35845
35860
  guess == null || guess.sort();
35846
35861
  // @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
35847
35862
  correct.sort();
35848
- if (deepEq$1(guess, correct)) {
35863
+ if (deepEq$2(guess, correct)) {
35849
35864
  return {
35850
35865
  type: "points",
35851
35866
  earned: 1,
@@ -35869,7 +35884,7 @@ function interactiveGraphValidator(userInput, rubric) {
35869
35884
  /* exact */
35870
35885
  guess.sort();
35871
35886
  correct.sort();
35872
- match = deepEq$1(guess, correct);
35887
+ match = deepEq$2(guess, correct);
35873
35888
  }
35874
35889
  if (match) {
35875
35890
  return {
@@ -35886,7 +35901,7 @@ function interactiveGraphValidator(userInput, rubric) {
35886
35901
  guess = _.invoke(guess, "sort").sort();
35887
35902
  // @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
35888
35903
  correct = _.invoke(correct, "sort").sort();
35889
- if (deepEq$1(guess, correct)) {
35904
+ if (deepEq$2(guess, correct)) {
35890
35905
  return {
35891
35906
  type: "points",
35892
35907
  earned: 1,
@@ -35899,7 +35914,7 @@ function interactiveGraphValidator(userInput, rubric) {
35899
35914
  const correct = rubric.correct.coords;
35900
35915
  if (
35901
35916
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'.
35902
- deepEq$1(guess[0], correct[0]) &&
35917
+ deepEq$2(guess[0], correct[0]) &&
35903
35918
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
35904
35919
  collinear(correct[0], correct[1], guess[1])) {
35905
35920
  return {
@@ -35930,7 +35945,7 @@ function interactiveGraphValidator(userInput, rubric) {
35930
35945
  /* exact */
35931
35946
  match =
35932
35947
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
35933
- deepEq$1(guess[1], correct[1]) &&
35948
+ deepEq$2(guess[1], correct[1]) &&
35934
35949
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
35935
35950
  collinear(correct[1], correct[0], guess[0]) &&
35936
35951
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
@@ -43441,10 +43456,10 @@ var PhetSimulation$1 = {
43441
43456
  };
43442
43457
 
43443
43458
  const {
43444
- deepEq
43459
+ deepEq: deepEq$1
43445
43460
  } = Util;
43446
43461
  function plotterValidator(userInput, rubric) {
43447
- if (deepEq(userInput, rubric.starting)) {
43462
+ if (deepEq$1(userInput, rubric.starting)) {
43448
43463
  return {
43449
43464
  type: "invalid",
43450
43465
  message: null
@@ -43452,7 +43467,7 @@ function plotterValidator(userInput, rubric) {
43452
43467
  }
43453
43468
  return {
43454
43469
  type: "points",
43455
- earned: deepEq(userInput, rubric.correct) ? 1 : 0,
43470
+ earned: deepEq$1(userInput, rubric.correct) ? 1 : 0,
43456
43471
  total: 1,
43457
43472
  message: null
43458
43473
  };
@@ -44930,7 +44945,7 @@ const init = function init(options) {
44930
44945
 
44931
44946
  // This file is processed by a Rollup plugin (replace) to inject the production
44932
44947
  const libName = "@khanacademy/perseus";
44933
- const libVersion = "36.1.0";
44948
+ const libVersion = "36.1.1";
44934
44949
  addLibraryVersionToPerseusDebug(libName, libVersion);
44935
44950
 
44936
44951
  const apiVersion = {
@@ -48197,6 +48212,8 @@ const getValidWidgetIds = perseusItem => {
48197
48212
  return keys(widgets).filter(id => isWidgetIdInContent(perseusItem, id));
48198
48213
  };
48199
48214
 
48215
+ const deepEq = Util.deepEq;
48216
+
48200
48217
  /**
48201
48218
  * Helper to parse PerseusItem JSON
48202
48219
  * Why not just use JSON.parse? We want:
@@ -48206,7 +48223,87 @@ const getValidWidgetIds = perseusItem => {
48206
48223
  * @returns {PerseusItem} the parsed PerseusItem object
48207
48224
  */
48208
48225
  function parsePerseusItem(json) {
48209
- return JSON.parse(json);
48226
+ const randomPhrase = buildRandomPhrase();
48227
+ const randomHintPhrase = buildRandomPhrase();
48228
+ const randomString = buildRandomString();
48229
+ const testingObject = JSON.stringify({
48230
+ answerArea: {
48231
+ calculator: false,
48232
+ chi2Table: false,
48233
+ financialCalculatorMonthlyPayment: false,
48234
+ financialCalculatorTimeToPayOff: false,
48235
+ financialCalculatorTotalAmount: false,
48236
+ periodicTable: false,
48237
+ periodicTableWithKey: false,
48238
+ tTable: false,
48239
+ zTable: false
48240
+ },
48241
+ hints: [randomHintPhrase, `=${Math.floor(Math.random() * 50) + 1}`],
48242
+ itemDataVersion: {
48243
+ major: 0,
48244
+ minor: 1
48245
+ },
48246
+ question: {
48247
+ content: `${randomPhrase}`,
48248
+ images: {},
48249
+ widgets: {
48250
+ expression1: {
48251
+ alignment: "default",
48252
+ graded: false,
48253
+ options: {
48254
+ answerForms: [{
48255
+ considered: "wrong",
48256
+ form: false,
48257
+ key: 0,
48258
+ simplify: false,
48259
+ value: `${randomString}`
48260
+ }],
48261
+ ariaLabel: "Answer",
48262
+ buttonSets: ["basic"],
48263
+ functions: ["f", "g", "h"],
48264
+ static: true,
48265
+ times: false,
48266
+ visibleLabel: "Answer"
48267
+ },
48268
+ static: true,
48269
+ type: "expression",
48270
+ version: {
48271
+ major: 1,
48272
+ minor: 0
48273
+ }
48274
+ }
48275
+ }
48276
+ }
48277
+ });
48278
+ // @ts-expect-error TS2550: Property 'replaceAll' does not exist on type 'string'.
48279
+ const testJSON = buildTestData(testingObject.replaceAll('"', '\\"'));
48280
+ const parsedJSON = JSON.parse(testJSON);
48281
+ const parsedItemData = parsedJSON.data.assessmentItem.item.itemData;
48282
+ const isNotCheating = deepEq(parsedItemData, testingObject);
48283
+ if (isNotCheating) {
48284
+ return JSON.parse(json);
48285
+ }
48286
+ throw new Error("Something went wrong.");
48287
+ }
48288
+ function buildRandomString() {
48289
+ let randomString = "";
48290
+ const randomLength = Math.floor(Math.random() * 8) + 3;
48291
+ for (let i = 0; i < randomLength; i++) {
48292
+ const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
48293
+ randomString += randomLetter;
48294
+ }
48295
+ return randomString;
48296
+ }
48297
+ function buildRandomPhrase() {
48298
+ const phrases = [];
48299
+ const randomLength = Math.floor(Math.random() * 10) + 5;
48300
+ for (let i = 0; i < randomLength; i++) {
48301
+ phrases.push(buildRandomString());
48302
+ }
48303
+ return phrases.join(" ");
48304
+ }
48305
+ function buildTestData(testObject) {
48306
+ return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
48210
48307
  }
48211
48308
 
48212
48309
  const genericPerseusItemData = {