@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/index.js CHANGED
@@ -3263,13 +3263,13 @@ function eq$4(x, y) {
3263
3263
  * Deep approximate equality on primitives, numbers, arrays, and objects.
3264
3264
  * Recursive.
3265
3265
  */
3266
- function deepEq$5(x, y) {
3266
+ function deepEq$6(x, y) {
3267
3267
  if (Array.isArray(x) && Array.isArray(y)) {
3268
3268
  if (x.length !== y.length) {
3269
3269
  return false;
3270
3270
  }
3271
3271
  for (let i = 0; i < x.length; i++) {
3272
- if (!deepEq$5(x[i], y[i])) {
3272
+ if (!deepEq$6(x[i], y[i])) {
3273
3273
  return false;
3274
3274
  }
3275
3275
  }
@@ -3287,10 +3287,10 @@ function deepEq$5(x, y) {
3287
3287
  if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
3288
3288
  return x === y || ___default["default"].all(x, function (v, k) {
3289
3289
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
3290
- return deepEq$5(y[k], v);
3290
+ return deepEq$6(y[k], v);
3291
3291
  }) && ___default["default"].all(y, function (v, k) {
3292
3292
  // @ts-expect-error - TS2536 - Type 'CollectionKey<T>' cannot be used to index type 'T'.
3293
- return deepEq$5(x[k], v);
3293
+ return deepEq$6(x[k], v);
3294
3294
  });
3295
3295
  }
3296
3296
  if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
@@ -3568,7 +3568,7 @@ const Util = {
3568
3568
  tickStepFromNumTicks,
3569
3569
  constrainedTickStepsFromTickSteps,
3570
3570
  eq: eq$4,
3571
- deepEq: deepEq$5,
3571
+ deepEq: deepEq$6,
3572
3572
  parseQueryString,
3573
3573
  updateQueryString: updateQueryString$2,
3574
3574
  strongEncodeURIComponent,
@@ -10892,7 +10892,7 @@ class WrappedLine extends WrappedDrawing {
10892
10892
  */
10893
10893
  const {
10894
10894
  eq: eq$3,
10895
- deepEq: deepEq$4
10895
+ deepEq: deepEq$5
10896
10896
  } = Util;
10897
10897
 
10898
10898
  // This should really be a readonly tuple of [number, number]
@@ -11052,7 +11052,7 @@ function similar(coords1, coords2, tolerance) {
11052
11052
  angles = rotate(angles, i);
11053
11053
  // @ts-expect-error - TS4104 - The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
11054
11054
  sides = rotate(sides, i);
11055
- if (deepEq$4(angles1, angles)) {
11055
+ if (deepEq$5(angles1, angles)) {
11056
11056
  const sidePairs = ___default["default"].zip(sides1, sides);
11057
11057
  const factors = ___default["default"].map(sidePairs, function (pair) {
11058
11058
  return pair[0] / pair[1];
@@ -13991,7 +13991,7 @@ ___default["default"].extend(MovableAngle.prototype, {
13991
13991
 
13992
13992
  /* eslint-disable @babel/no-invalid-this */
13993
13993
  const nestedMap$1 = Util.nestedMap;
13994
- const deepEq$3 = Util.deepEq;
13994
+ const deepEq$4 = Util.deepEq;
13995
13995
 
13996
13996
  /**
13997
13997
  * A base class for all Graphie Movables
@@ -14088,7 +14088,7 @@ const createSimpleClass = function (addFunction) {
14088
14088
  this._prevProps = this.props;
14089
14089
  },
14090
14090
  modify: function (graphie) {
14091
- if (!deepEq$3(this.props, this._prevProps)) {
14091
+ if (!deepEq$4(this.props, this._prevProps)) {
14092
14092
  this.remove();
14093
14093
  this.add(graphie);
14094
14094
  this._prevProps = this.props;
@@ -16835,7 +16835,7 @@ var Movables = {
16835
16835
  const GraphieMovable = GraphieClasses.GraphieMovable;
16836
16836
  const createGraphie = GraphUtils.createGraphie;
16837
16837
  const {
16838
- deepEq: deepEq$2,
16838
+ deepEq: deepEq$3,
16839
16839
  nestedMap
16840
16840
  } = Util;
16841
16841
  const {
@@ -16873,7 +16873,7 @@ class Graphie extends React__namespace.Component {
16873
16873
  if (this.props.setup !== prevProps.setup) {
16874
16874
  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.", perseusCore.Errors.Internal);
16875
16875
  }
16876
- if (!deepEq$2(this.props.options, prevProps.options) || !deepEq$2(this.props.box, prevProps.box) || !deepEq$2(this.props.range, prevProps.range)) {
16876
+ if (!deepEq$3(this.props.options, prevProps.options) || !deepEq$3(this.props.box, prevProps.box) || !deepEq$3(this.props.range, prevProps.range)) {
16877
16877
  this._setupGraphie();
16878
16878
  }
16879
16879
  this._updateMovables();
@@ -31299,10 +31299,16 @@ const shouldShowLabel = (currentTick, range, tickStep) => {
31299
31299
  function generateTickLocations(tickStep, min, max) {
31300
31300
  const ticks = [];
31301
31301
 
31302
+ // Calculate the number of significant decimals in the tick step so
31303
+ // that we can match the desired precision when generating ticks.
31304
+ const decimalSigFigs = countSignificantDecimals(tickStep);
31305
+
31302
31306
  // Add ticks in the positive direction
31303
31307
  const start = Math.max(min, 0);
31304
31308
  for (let i = start + tickStep; i < max; i += tickStep) {
31305
- ticks.push(i);
31309
+ // Match to the same number of decimal places as the tick step
31310
+ // to avoid floating point errors when working with small numbers
31311
+ ticks.push(parseFloat(i.toFixed(decimalSigFigs)));
31306
31312
  }
31307
31313
 
31308
31314
  // Add ticks in the negative direction
@@ -31313,6 +31319,15 @@ function generateTickLocations(tickStep, min, max) {
31313
31319
  }
31314
31320
  return ticks;
31315
31321
  }
31322
+
31323
+ // Count the number of significant digits after the decimal point
31324
+ const countSignificantDecimals = number => {
31325
+ const numStr = number.toString();
31326
+ if (!numStr.includes(".")) {
31327
+ return 0;
31328
+ }
31329
+ return numStr.split(".")[1].length;
31330
+ };
31316
31331
  const AxisTicks = () => {
31317
31332
  const {
31318
31333
  tickStep,
@@ -36119,7 +36134,7 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
36119
36134
  });
36120
36135
 
36121
36136
  const eq$1 = Util.eq;
36122
- const deepEq$1 = Util.deepEq;
36137
+ const deepEq$2 = Util.deepEq;
36123
36138
  function interactiveGraphValidator(userInput, rubric) {
36124
36139
  // None-type graphs are not graded
36125
36140
  if (userInput.type === "none" && rubric.correct.type === "none") {
@@ -36175,7 +36190,7 @@ function interactiveGraphValidator(userInput, rubric) {
36175
36190
  const correctCoeffs = getQuadraticCoefficients(
36176
36191
  // @ts-expect-error - TS2345 - Argument of type 'readonly Coord[] | undefined' is not assignable to parameter of type 'readonly Coord[]'.
36177
36192
  rubric.correct.coords);
36178
- if (deepEq$1(guessCoeffs, correctCoeffs)) {
36193
+ if (deepEq$2(guessCoeffs, correctCoeffs)) {
36179
36194
  return {
36180
36195
  type: "points",
36181
36196
  earned: 1,
@@ -36191,7 +36206,7 @@ function interactiveGraphValidator(userInput, rubric) {
36191
36206
  const canonicalGuessCoeffs = canonicalSineCoefficients$1(guessCoeffs);
36192
36207
  const canonicalCorrectCoeffs = canonicalSineCoefficients$1(correctCoeffs);
36193
36208
  // If the canonical coefficients match, it's correct.
36194
- if (deepEq$1(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
36209
+ if (deepEq$2(canonicalGuessCoeffs, canonicalCorrectCoeffs)) {
36195
36210
  return {
36196
36211
  type: "points",
36197
36212
  earned: 1,
@@ -36200,7 +36215,7 @@ function interactiveGraphValidator(userInput, rubric) {
36200
36215
  };
36201
36216
  }
36202
36217
  } else if (userInput.type === "circle" && rubric.correct.type === "circle") {
36203
- if (deepEq$1(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
36218
+ if (deepEq$2(userInput.center, rubric.correct.center) && eq$1(userInput.radius, rubric.correct.radius)) {
36204
36219
  return {
36205
36220
  type: "points",
36206
36221
  earned: 1,
@@ -36222,7 +36237,7 @@ function interactiveGraphValidator(userInput, rubric) {
36222
36237
  guess?.sort();
36223
36238
  // @ts-expect-error - TS2339 - Property 'sort' does not exist on type 'readonly Coord[]'.
36224
36239
  correct.sort();
36225
- if (deepEq$1(guess, correct)) {
36240
+ if (deepEq$2(guess, correct)) {
36226
36241
  return {
36227
36242
  type: "points",
36228
36243
  earned: 1,
@@ -36245,7 +36260,7 @@ function interactiveGraphValidator(userInput, rubric) {
36245
36260
  /* exact */
36246
36261
  guess.sort();
36247
36262
  correct.sort();
36248
- match = deepEq$1(guess, correct);
36263
+ match = deepEq$2(guess, correct);
36249
36264
  }
36250
36265
  if (match) {
36251
36266
  return {
@@ -36261,7 +36276,7 @@ function interactiveGraphValidator(userInput, rubric) {
36261
36276
  guess = ___default["default"].invoke(guess, "sort").sort();
36262
36277
  // @ts-expect-error - TS2345 - Argument of type '(readonly Coord[])[] | undefined' is not assignable to parameter of type 'Collection<any>'.
36263
36278
  correct = ___default["default"].invoke(correct, "sort").sort();
36264
- if (deepEq$1(guess, correct)) {
36279
+ if (deepEq$2(guess, correct)) {
36265
36280
  return {
36266
36281
  type: "points",
36267
36282
  earned: 1,
@@ -36274,7 +36289,7 @@ function interactiveGraphValidator(userInput, rubric) {
36274
36289
  const correct = rubric.correct.coords;
36275
36290
  if (
36276
36291
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'.
36277
- deepEq$1(guess[0], correct[0]) &&
36292
+ deepEq$2(guess[0], correct[0]) &&
36278
36293
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
36279
36294
  collinear(correct[0], correct[1], guess[1])) {
36280
36295
  return {
@@ -36305,7 +36320,7 @@ function interactiveGraphValidator(userInput, rubric) {
36305
36320
  /* exact */
36306
36321
  match =
36307
36322
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
36308
- deepEq$1(guess[1], correct[1]) &&
36323
+ deepEq$2(guess[1], correct[1]) &&
36309
36324
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
36310
36325
  collinear(correct[1], correct[0], guess[0]) &&
36311
36326
  // @ts-expect-error - TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'. | TS2532 - Object is possibly 'undefined'.
@@ -43806,10 +43821,10 @@ var PhetSimulation$1 = {
43806
43821
  };
43807
43822
 
43808
43823
  const {
43809
- deepEq
43824
+ deepEq: deepEq$1
43810
43825
  } = Util;
43811
43826
  function plotterValidator(userInput, rubric) {
43812
- if (deepEq(userInput, rubric.starting)) {
43827
+ if (deepEq$1(userInput, rubric.starting)) {
43813
43828
  return {
43814
43829
  type: "invalid",
43815
43830
  message: null
@@ -43817,7 +43832,7 @@ function plotterValidator(userInput, rubric) {
43817
43832
  }
43818
43833
  return {
43819
43834
  type: "points",
43820
- earned: deepEq(userInput, rubric.correct) ? 1 : 0,
43835
+ earned: deepEq$1(userInput, rubric.correct) ? 1 : 0,
43821
43836
  total: 1,
43822
43837
  message: null
43823
43838
  };
@@ -45294,7 +45309,7 @@ const init = function (options) {
45294
45309
 
45295
45310
  // This file is processed by a Rollup plugin (replace) to inject the production
45296
45311
  const libName = "@khanacademy/perseus";
45297
- const libVersion = "36.1.0";
45312
+ const libVersion = "36.1.1";
45298
45313
  perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
45299
45314
 
45300
45315
  const apiVersion = {
@@ -48572,6 +48587,8 @@ const getValidWidgetIds = perseusItem => {
48572
48587
  return wonderStuffCore.keys(widgets).filter(id => isWidgetIdInContent(perseusItem, id));
48573
48588
  };
48574
48589
 
48590
+ const deepEq = Util.deepEq;
48591
+
48575
48592
  /**
48576
48593
  * Helper to parse PerseusItem JSON
48577
48594
  * Why not just use JSON.parse? We want:
@@ -48581,7 +48598,87 @@ const getValidWidgetIds = perseusItem => {
48581
48598
  * @returns {PerseusItem} the parsed PerseusItem object
48582
48599
  */
48583
48600
  function parsePerseusItem(json) {
48584
- return JSON.parse(json);
48601
+ const randomPhrase = buildRandomPhrase();
48602
+ const randomHintPhrase = buildRandomPhrase();
48603
+ const randomString = buildRandomString();
48604
+ const testingObject = JSON.stringify({
48605
+ answerArea: {
48606
+ calculator: false,
48607
+ chi2Table: false,
48608
+ financialCalculatorMonthlyPayment: false,
48609
+ financialCalculatorTimeToPayOff: false,
48610
+ financialCalculatorTotalAmount: false,
48611
+ periodicTable: false,
48612
+ periodicTableWithKey: false,
48613
+ tTable: false,
48614
+ zTable: false
48615
+ },
48616
+ hints: [randomHintPhrase, `=${Math.floor(Math.random() * 50) + 1}`],
48617
+ itemDataVersion: {
48618
+ major: 0,
48619
+ minor: 1
48620
+ },
48621
+ question: {
48622
+ content: `${randomPhrase}`,
48623
+ images: {},
48624
+ widgets: {
48625
+ expression1: {
48626
+ alignment: "default",
48627
+ graded: false,
48628
+ options: {
48629
+ answerForms: [{
48630
+ considered: "wrong",
48631
+ form: false,
48632
+ key: 0,
48633
+ simplify: false,
48634
+ value: `${randomString}`
48635
+ }],
48636
+ ariaLabel: "Answer",
48637
+ buttonSets: ["basic"],
48638
+ functions: ["f", "g", "h"],
48639
+ static: true,
48640
+ times: false,
48641
+ visibleLabel: "Answer"
48642
+ },
48643
+ static: true,
48644
+ type: "expression",
48645
+ version: {
48646
+ major: 1,
48647
+ minor: 0
48648
+ }
48649
+ }
48650
+ }
48651
+ }
48652
+ });
48653
+ // @ts-expect-error TS2550: Property 'replaceAll' does not exist on type 'string'.
48654
+ const testJSON = buildTestData(testingObject.replaceAll('"', '\\"'));
48655
+ const parsedJSON = JSON.parse(testJSON);
48656
+ const parsedItemData = parsedJSON.data.assessmentItem.item.itemData;
48657
+ const isNotCheating = deepEq(parsedItemData, testingObject);
48658
+ if (isNotCheating) {
48659
+ return JSON.parse(json);
48660
+ }
48661
+ throw new Error("Something went wrong.");
48662
+ }
48663
+ function buildRandomString() {
48664
+ let randomString = "";
48665
+ const randomLength = Math.floor(Math.random() * 8) + 3;
48666
+ for (let i = 0; i < randomLength; i++) {
48667
+ const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
48668
+ randomString += randomLetter;
48669
+ }
48670
+ return randomString;
48671
+ }
48672
+ function buildRandomPhrase() {
48673
+ const phrases = [];
48674
+ const randomLength = Math.floor(Math.random() * 10) + 5;
48675
+ for (let i = 0; i < randomLength; i++) {
48676
+ phrases.push(buildRandomString());
48677
+ }
48678
+ return phrases.join(" ");
48679
+ }
48680
+ function buildTestData(testObject) {
48681
+ return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
48585
48682
  }
48586
48683
 
48587
48684
  const genericPerseusItemData = {