@khanacademy/perseus-core 6.0.0 → 7.0.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
@@ -1,456 +1,45 @@
1
- import _ from 'underscore';
2
- import _extends from '@babel/runtime/helpers/extends';
3
- import * as KAS from '@khanacademy/kas';
4
- import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/objectWithoutPropertiesLoose';
5
- import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
6
-
7
- function getMatrixSize(matrix) {
8
- const matrixSize = [1, 1];
9
- _(matrix).each((matrixRow, row) => {
10
- let rowWidth = 0;
11
- _(matrixRow).each((matrixCol, col) => {
12
- if (matrixCol != null && matrixCol.toString().length) {
13
- rowWidth = col + 1;
14
- }
15
- });
16
- matrixSize[1] = Math.max(matrixSize[1], rowWidth);
17
- if (rowWidth > 0) {
18
- matrixSize[0] = Math.max(matrixSize[0], row + 1);
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _ = require('underscore');
6
+ var KAS = require('@khanacademy/kas');
7
+ var perseusUtils = require('@khanacademy/perseus-utils');
8
+
9
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
10
+
11
+ function _interopNamespaceCompat(e) {
12
+ if (e && typeof e === 'object' && 'default' in e) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
19
24
  }
20
- });
21
- return matrixSize;
25
+ n.default = e;
26
+ return Object.freeze(n);
22
27
  }
23
28
 
24
- const getDecimalSeparator = locale => {
25
- var _match$;
26
- switch (locale) {
27
- case "ka":
28
- return ",";
29
- default:
30
- const numberWithDecimalSeparator = 1.1;
31
- const match = new Intl.NumberFormat(locale).format(numberWithDecimalSeparator).match(/[^\d\u0661\u06F1\u0967\u09e7]/);
32
- return (_match$ = match == null ? void 0 : match[0]) != null ? _match$ : ".";
33
- }
34
- };
35
-
36
- function approximateEqual(x, y) {
37
- if (typeof x === "number" && typeof y === "number") {
38
- return Math.abs(x - y) < 1e-9;
39
- }
40
- return x === y;
41
- }
42
- function approximateDeepEqual(x, y) {
43
- if (Array.isArray(x) && Array.isArray(y)) {
44
- if (x.length !== y.length) {
45
- return false;
46
- }
47
- for (let i = 0; i < x.length; i++) {
48
- if (!approximateDeepEqual(x[i], y[i])) {
49
- return false;
50
- }
51
- }
52
- return true;
53
- }
54
- if (Array.isArray(x) || Array.isArray(y)) {
55
- return false;
56
- }
57
- if (typeof x === "function" && typeof y === "function") {
58
- return approximateEqual(x, y);
59
- }
60
- if (typeof x === "function" || typeof y === "function") {
61
- return false;
62
- }
63
- if (typeof x === "object" && typeof y === "object" && !!x && !!y) {
64
- return x === y || _.all(x, function (v, k) {
65
- return approximateDeepEqual(y[k], v);
66
- }) && _.all(y, function (v, k) {
67
- return approximateDeepEqual(x[k], v);
68
- });
69
- }
70
- if (typeof x === "object" && !!x || typeof y === "object" && !!y) {
71
- return false;
72
- }
73
- return approximateEqual(x, y);
74
- }
29
+ var ___default = /*#__PURE__*/_interopDefaultCompat(_);
30
+ var KAS__namespace = /*#__PURE__*/_interopNamespaceCompat(KAS);
75
31
 
76
- function addWidget(id) {
77
- return `[[☃ ${id}]]`;
78
- }
79
- function getWidgetRegex() {
80
- return /\[\[☃ ([A-Za-z0-9- ]+)\]\]/g;
81
- }
82
- function getWidgetIdsFromContent(content) {
83
- const widgets = [];
84
- const localWidgetRegex = getWidgetRegex();
85
- let match = localWidgetRegex.exec(content);
86
- while (match !== null) {
87
- widgets.push(match[1]);
88
- match = localWidgetRegex.exec(content);
89
- }
90
- return widgets;
91
- }
92
- function getWidgetIdsFromContentByType(type, content, widgetMap) {
93
- const rv = [];
94
- const widgetIdsInContent = getWidgetIdsFromContent(content);
95
- widgetIdsInContent.forEach(widgetId => {
96
- const widget = widgetMap[widgetId];
97
- if ((widget == null ? void 0 : widget.type) === type) {
98
- rv.push(widgetId);
99
- }
100
- });
101
- return rv;
102
- }
32
+ function getMatrixSize(matrix){const matrixSize=[1,1];___default.default(matrix).each((matrixRow,row)=>{let rowWidth=0;___default.default(matrixRow).each((matrixCol,col)=>{if(matrixCol!=null&&matrixCol.toString().length){rowWidth=col+1;}});matrixSize[1]=Math.max(matrixSize[1],rowWidth);if(rowWidth>0){matrixSize[0]=Math.max(matrixSize[0],row+1);}});return matrixSize}
103
33
 
104
- function deepClone(obj) {
105
- if (Array.isArray(obj)) {
106
- return obj.map(deepClone);
107
- }
108
- return obj;
109
- }
34
+ const getDecimalSeparator=locale=>{switch(locale){case "ka":return ",";default:const numberWithDecimalSeparator=1.1;const match=new Intl.NumberFormat(locale).format(numberWithDecimalSeparator).match(/[^\d\u0661\u06F1\u0967\u09e7]/);return match?.[0]??"."}};
110
35
 
111
- const MOVABLES = {
112
- PLOT: "PLOT",
113
- PARABOLA: "PARABOLA",
114
- SINUSOID: "SINUSOID"
115
- };
116
- function canonicalSineCoefficients(coeffs) {
117
- let amplitude = coeffs[0];
118
- let angularFrequency = coeffs[1];
119
- let phase = coeffs[2];
120
- const verticalOffset = coeffs[3];
121
- if (amplitude < 0) {
122
- amplitude *= -1;
123
- angularFrequency *= -1;
124
- phase *= -1;
125
- }
126
- const period = 2 * Math.PI;
127
- if (angularFrequency < 0) {
128
- angularFrequency *= -1;
129
- phase *= -1;
130
- phase += period / 2;
131
- }
132
- while (phase > 0) {
133
- phase -= period;
134
- }
135
- while (phase < 0) {
136
- phase += period;
137
- }
138
- return [amplitude, angularFrequency, phase, verticalOffset];
139
- }
140
- function canonicalTangentCoefficients(coeffs) {
141
- let amplitude = coeffs[0];
142
- let angularFrequency = coeffs[1];
143
- let phase = coeffs[2];
144
- const verticalOffset = coeffs[3];
145
- if (amplitude < 0) {
146
- amplitude *= -1;
147
- angularFrequency *= -1;
148
- phase *= -1;
149
- }
150
- const period = Math.PI;
151
- if (angularFrequency < 0) {
152
- angularFrequency *= -1;
153
- phase *= -1;
154
- phase += period / 2;
155
- }
156
- while (phase > 0) {
157
- phase -= period;
158
- }
159
- while (phase < 0) {
160
- phase += period;
161
- }
162
- return [amplitude, angularFrequency, phase, verticalOffset];
163
- }
164
- const PlotDefaults = {
165
- areEqual: function (coeffs1, coeffs2) {
166
- return approximateDeepEqual(coeffs1, coeffs2);
167
- },
168
- movable: MOVABLES.PLOT,
169
- getPropsForCoeffs: function (coeffs) {
170
- return {
171
- fn: _.partial(this.getFunctionForCoeffs, coeffs)
172
- };
173
- }
174
- };
175
- const Linear = _.extend({}, PlotDefaults, {
176
- url: "https://ka-perseus-graphie.s3.amazonaws.com/67aaf581e6d9ef9038c10558a1f70ac21c11c9f8.png",
177
- defaultCoords: [[0.25, 0.75], [0.75, 0.75]],
178
- getCoefficients: function (coords) {
179
- const p1 = coords[0];
180
- const p2 = coords[1];
181
- const denom = p2[0] - p1[0];
182
- const num = p2[1] - p1[1];
183
- if (denom === 0) {
184
- return;
185
- }
186
- const m = num / denom;
187
- const b = p2[1] - m * p2[0];
188
- return [m, b];
189
- },
190
- getFunctionForCoeffs: function (coeffs, x) {
191
- const m = coeffs[0];
192
- const b = coeffs[1];
193
- return m * x + b;
194
- },
195
- getEquationString: function (coords) {
196
- const coeffs = this.getCoefficients(coords);
197
- const m = coeffs[0];
198
- const b = coeffs[1];
199
- return "y = " + m.toFixed(3) + "x + " + b.toFixed(3);
200
- }
201
- });
202
- const Quadratic = _.extend({}, PlotDefaults, {
203
- url: "https://ka-perseus-graphie.s3.amazonaws.com/e23d36e6fc29ee37174e92c9daba2a66677128ab.png",
204
- defaultCoords: [[0.5, 0.5], [0.75, 0.75]],
205
- movable: MOVABLES.PARABOLA,
206
- getCoefficients: function (coords) {
207
- const p1 = coords[0];
208
- const p2 = coords[1];
209
- const h = p1[0];
210
- const k = p1[1];
211
- const a = (p2[1] - k) / ((p2[0] - h) * (p2[0] - h));
212
- const b = -2 * h * a;
213
- const c = a * h * h + k;
214
- return [a, b, c];
215
- },
216
- getFunctionForCoeffs: function (coeffs, x) {
217
- const a = coeffs[0];
218
- const b = coeffs[1];
219
- const c = coeffs[2];
220
- return (a * x + b) * x + c;
221
- },
222
- getPropsForCoeffs: function (coeffs) {
223
- return {
224
- a: coeffs[0],
225
- b: coeffs[1],
226
- c: coeffs[2]
227
- };
228
- },
229
- getEquationString: function (coords) {
230
- const coeffs = this.getCoefficients(coords);
231
- const a = coeffs[0];
232
- const b = coeffs[1];
233
- const c = coeffs[2];
234
- return "y = " + a.toFixed(3) + "x^2 + " + b.toFixed(3) + "x + " + c.toFixed(3);
235
- }
236
- });
237
- const Sinusoid = _.extend({}, PlotDefaults, {
238
- url: "https://ka-perseus-graphie.s3.amazonaws.com/3d68e7718498475f53b206c2ab285626baf8857e.png",
239
- defaultCoords: [[0.5, 0.5], [0.6, 0.6]],
240
- movable: MOVABLES.SINUSOID,
241
- getCoefficients: function (coords) {
242
- const p1 = coords[0];
243
- const p2 = coords[1];
244
- const a = p2[1] - p1[1];
245
- const b = Math.PI / (2 * (p2[0] - p1[0]));
246
- const c = p1[0] * b;
247
- const d = p1[1];
248
- return [a, b, c, d];
249
- },
250
- getFunctionForCoeffs: function (coeffs, x) {
251
- const a = coeffs[0];
252
- const b = coeffs[1];
253
- const c = coeffs[2];
254
- const d = coeffs[3];
255
- return a * Math.sin(b * x - c) + d;
256
- },
257
- getPropsForCoeffs: function (coeffs) {
258
- return {
259
- a: coeffs[0],
260
- b: coeffs[1],
261
- c: coeffs[2],
262
- d: coeffs[3]
263
- };
264
- },
265
- getEquationString: function (coords) {
266
- const coeffs = this.getCoefficients(coords);
267
- const a = coeffs[0];
268
- const b = coeffs[1];
269
- const c = coeffs[2];
270
- const d = coeffs[3];
271
- return "y = " + a.toFixed(3) + " sin(" + b.toFixed(3) + "x - " + c.toFixed(3) + ") + " + d.toFixed(3);
272
- },
273
- areEqual: function (coeffs1, coeffs2) {
274
- return approximateDeepEqual(canonicalSineCoefficients(coeffs1), canonicalSineCoefficients(coeffs2));
275
- }
276
- });
277
- const Tangent = _.extend({}, PlotDefaults, {
278
- url: "https://ka-perseus-graphie.s3.amazonaws.com/7db80d23c35214f98659fe1cf0765811c1bbfbba.png",
279
- defaultCoords: [[0.5, 0.5], [0.75, 0.75]],
280
- getCoefficients: function (coords) {
281
- const p1 = coords[0];
282
- const p2 = coords[1];
283
- const a = p2[1] - p1[1];
284
- const b = Math.PI / (4 * (p2[0] - p1[0]));
285
- const c = p1[0] * b;
286
- const d = p1[1];
287
- return [a, b, c, d];
288
- },
289
- getFunctionForCoeffs: function (coeffs, x) {
290
- const a = coeffs[0];
291
- const b = coeffs[1];
292
- const c = coeffs[2];
293
- const d = coeffs[3];
294
- return a * Math.tan(b * x - c) + d;
295
- },
296
- getEquationString: function (coords) {
297
- const coeffs = this.getCoefficients(coords);
298
- const a = coeffs[0];
299
- const b = coeffs[1];
300
- const c = coeffs[2];
301
- const d = coeffs[3];
302
- return "y = " + a.toFixed(3) + " sin(" + b.toFixed(3) + "x - " + c.toFixed(3) + ") + " + d.toFixed(3);
303
- },
304
- areEqual: function (coeffs1, coeffs2) {
305
- return approximateDeepEqual(canonicalTangentCoefficients(coeffs1), canonicalTangentCoefficients(coeffs2));
306
- }
307
- });
308
- const Exponential = _.extend({}, PlotDefaults, {
309
- url: "https://ka-perseus-graphie.s3.amazonaws.com/9cbfad55525e3ce755a31a631b074670a5dad611.png",
310
- defaultCoords: [[0.5, 0.55], [0.75, 0.75]],
311
- defaultAsymptote: [[0, 0.5], [1.0, 0.5]],
312
- extraCoordConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
313
- const y = asymptote[0][1];
314
- return _.all(coords, coord => coord[1] !== y);
315
- },
316
- extraAsymptoteConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
317
- const y = newCoord[1];
318
- const isValid = _.all(coords, coord => coord[1] > y) || _.all(coords, coord => coord[1] < y);
319
- if (isValid) {
320
- return [oldCoord[0], y];
321
- }
322
- const oldY = oldCoord[1];
323
- const wasBelow = _.all(coords, coord => coord[1] > oldY);
324
- if (wasBelow) {
325
- const bottomMost = _.min(_.map(coords, coord => coord[1]));
326
- return [oldCoord[0], bottomMost - graph.snapStep[1]];
327
- }
328
- const topMost = _.max(_.map(coords, coord => coord[1]));
329
- return [oldCoord[0], topMost + graph.snapStep[1]];
330
- },
331
- allowReflectOverAsymptote: true,
332
- getCoefficients: function (coords, asymptote) {
333
- const p1 = coords[0];
334
- const p2 = coords[1];
335
- const c = asymptote[0][1];
336
- const b = Math.log((p1[1] - c) / (p2[1] - c)) / (p1[0] - p2[0]);
337
- const a = (p1[1] - c) / Math.exp(b * p1[0]);
338
- return [a, b, c];
339
- },
340
- getFunctionForCoeffs: function (coeffs, x) {
341
- const a = coeffs[0];
342
- const b = coeffs[1];
343
- const c = coeffs[2];
344
- return a * Math.exp(b * x) + c;
345
- },
346
- getEquationString: function (coords, asymptote) {
347
- if (!asymptote) {
348
- return null;
349
- }
350
- const coeffs = this.getCoefficients(coords, asymptote);
351
- const a = coeffs[0];
352
- const b = coeffs[1];
353
- const c = coeffs[2];
354
- return "y = " + a.toFixed(3) + "e^(" + b.toFixed(3) + "x) + " + c.toFixed(3);
355
- }
356
- });
357
- const Logarithm = _.extend({}, PlotDefaults, {
358
- url: "https://ka-perseus-graphie.s3.amazonaws.com/f6491e99d34af34d924bfe0231728ad912068dc3.png",
359
- defaultCoords: [[0.55, 0.5], [0.75, 0.75]],
360
- defaultAsymptote: [[0.5, 0], [0.5, 1.0]],
361
- extraCoordConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
362
- const x = asymptote[0][0];
363
- return _.all(coords, coord => coord[0] !== x) && coords[0][1] !== coords[1][1];
364
- },
365
- extraAsymptoteConstraint: function (newCoord, oldCoord, coords, asymptote, graph) {
366
- const x = newCoord[0];
367
- const isValid = _.all(coords, coord => coord[0] > x) || _.all(coords, coord => coord[0] < x);
368
- if (isValid) {
369
- return [x, oldCoord[1]];
370
- }
371
- const oldX = oldCoord[0];
372
- const wasLeft = _.all(coords, coord => coord[0] > oldX);
373
- if (wasLeft) {
374
- const leftMost = _.min(_.map(coords, coord => coord[0]));
375
- return [leftMost - graph.snapStep[0], oldCoord[1]];
376
- }
377
- const rightMost = _.max(_.map(coords, coord => coord[0]));
378
- return [rightMost + graph.snapStep[0], oldCoord[1]];
379
- },
380
- allowReflectOverAsymptote: true,
381
- getCoefficients: function (coords, asymptote) {
382
- const flip = coord => [coord[1], coord[0]];
383
- const inverseCoeffs = Exponential.getCoefficients(_.map(coords, flip), _.map(asymptote, flip));
384
- if (inverseCoeffs) {
385
- const c = -inverseCoeffs[2] / inverseCoeffs[0];
386
- const b = 1 / inverseCoeffs[0];
387
- const a = 1 / inverseCoeffs[1];
388
- return [a, b, c];
389
- }
390
- },
391
- getFunctionForCoeffs: function (coeffs, x, asymptote) {
392
- const a = coeffs[0];
393
- const b = coeffs[1];
394
- const c = coeffs[2];
395
- return a * Math.log(b * x + c);
396
- },
397
- getEquationString: function (coords, asymptote) {
398
- if (!asymptote) {
399
- return null;
400
- }
401
- const coeffs = this.getCoefficients(coords, asymptote);
402
- const a = coeffs[0];
403
- const b = coeffs[1];
404
- const c = coeffs[2];
405
- return "y = ln(" + a.toFixed(3) + "x + " + b.toFixed(3) + ") + " + c.toFixed(3);
406
- }
407
- });
408
- const AbsoluteValue = _.extend({}, PlotDefaults, {
409
- url: "https://ka-perseus-graphie.s3.amazonaws.com/8256a630175a0cb1d11de223d6de0266daf98721.png",
410
- defaultCoords: [[0.5, 0.5], [0.75, 0.75]],
411
- getCoefficients: function (coords) {
412
- const p1 = coords[0];
413
- const p2 = coords[1];
414
- const denom = p2[0] - p1[0];
415
- const num = p2[1] - p1[1];
416
- if (denom === 0) {
417
- return;
418
- }
419
- let m = Math.abs(num / denom);
420
- if (p2[1] < p1[1]) {
421
- m *= -1;
422
- }
423
- const horizontalOffset = p1[0];
424
- const verticalOffset = p1[1];
425
- return [m, horizontalOffset, verticalOffset];
426
- },
427
- getFunctionForCoeffs: function (coeffs, x) {
428
- const m = coeffs[0];
429
- const horizontalOffset = coeffs[1];
430
- const verticalOffset = coeffs[2];
431
- return m * Math.abs(x - horizontalOffset) + verticalOffset;
432
- },
433
- getEquationString: function (coords) {
434
- const coeffs = this.getCoefficients(coords);
435
- const m = coeffs[0];
436
- const horizontalOffset = coeffs[1];
437
- const verticalOffset = coeffs[2];
438
- return "y = " + m.toFixed(3) + "| x - " + horizontalOffset.toFixed(3) + "| + " + verticalOffset.toFixed(3);
439
- }
440
- });
441
- const functionTypeMapping = {
442
- linear: Linear,
443
- quadratic: Quadratic,
444
- sinusoid: Sinusoid,
445
- tangent: Tangent,
446
- exponential: Exponential,
447
- logarithm: Logarithm,
448
- absolute_value: AbsoluteValue
449
- };
450
- const allTypes = _.keys(functionTypeMapping);
451
- function functionForType(type) {
452
- return functionTypeMapping[type];
453
- }
36
+ function approximateEqual(x,y){if(typeof x==="number"&&typeof y==="number"){return Math.abs(x-y)<1e-9}return x===y}function approximateDeepEqual(x,y){if(Array.isArray(x)&&Array.isArray(y)){if(x.length!==y.length){return false}for(let i=0;i<x.length;i++){if(!approximateDeepEqual(x[i],y[i])){return false}}return true}if(Array.isArray(x)||Array.isArray(y)){return false}if(typeof x==="function"&&typeof y==="function"){return approximateEqual(x,y)}if(typeof x==="function"||typeof y==="function"){return false}if(typeof x==="object"&&typeof y==="object"&&!!x&&!!y){return x===y||___default.default.all(x,function(v,k){return approximateDeepEqual(y[k],v)})&&___default.default.all(y,function(v,k){return approximateDeepEqual(x[k],v)})}if(typeof x==="object"&&!!x||typeof y==="object"&&!!y){return false}return approximateEqual(x,y)}
37
+
38
+ function addWidget(id){return `[[☃ ${id}]]`}function getWidgetRegex(){return /\[\[☃ ([A-Za-z0-9- ]+)\]\]/g}function getWidgetIdsFromContent(content){const widgets=[];const localWidgetRegex=getWidgetRegex();let match=localWidgetRegex.exec(content);while(match!==null){widgets.push(match[1]);match=localWidgetRegex.exec(content);}return widgets}function getWidgetIdsFromContentByType(type,content,widgetMap){const rv=[];const widgetIdsInContent=getWidgetIdsFromContent(content);widgetIdsInContent.forEach(widgetId=>{const widget=widgetMap[widgetId];if(widget?.type===type){rv.push(widgetId);}});return rv}
39
+
40
+ function deepClone(obj){if(Array.isArray(obj)){return obj.map(deepClone)}return obj}
41
+
42
+ const MOVABLES={PLOT:"PLOT",PARABOLA:"PARABOLA",SINUSOID:"SINUSOID"};function canonicalSineCoefficients(coeffs){let amplitude=coeffs[0];let angularFrequency=coeffs[1];let phase=coeffs[2];const verticalOffset=coeffs[3];if(amplitude<0){amplitude*=-1;angularFrequency*=-1;phase*=-1;}const period=2*Math.PI;if(angularFrequency<0){angularFrequency*=-1;phase*=-1;phase+=period/2;}while(phase>0){phase-=period;}while(phase<0){phase+=period;}return [amplitude,angularFrequency,phase,verticalOffset]}function canonicalTangentCoefficients(coeffs){let amplitude=coeffs[0];let angularFrequency=coeffs[1];let phase=coeffs[2];const verticalOffset=coeffs[3];if(amplitude<0){amplitude*=-1;angularFrequency*=-1;phase*=-1;}const period=Math.PI;if(angularFrequency<0){angularFrequency*=-1;phase*=-1;phase+=period/2;}while(phase>0){phase-=period;}while(phase<0){phase+=period;}return [amplitude,angularFrequency,phase,verticalOffset]}const PlotDefaults={areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(coeffs1,coeffs2)},movable:MOVABLES.PLOT,getPropsForCoeffs:function(coeffs){return {fn:___default.default.partial(this.getFunctionForCoeffs,coeffs)}}};const Linear=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/67aaf581e6d9ef9038c10558a1f70ac21c11c9f8.png",defaultCoords:[[.25,.75],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}const m=num/denom;const b=p2[1]-m*p2[0];return [m,b]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const b=coeffs[1];return m*x+b},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const b=coeffs[1];return "y = "+m.toFixed(3)+"x + "+b.toFixed(3)}});const Quadratic=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/e23d36e6fc29ee37174e92c9daba2a66677128ab.png",defaultCoords:[[.5,.5],[.75,.75]],movable:MOVABLES.PARABOLA,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const h=p1[0];const k=p1[1];const a=(p2[1]-k)/((p2[0]-h)*(p2[0]-h));const b=-2*h*a;const c=a*h*h+k;return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return (a*x+b)*x+c},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"x^2 + "+b.toFixed(3)+"x + "+c.toFixed(3)}});const Sinusoid=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/3d68e7718498475f53b206c2ab285626baf8857e.png",defaultCoords:[[.5,.5],[.6,.6]],movable:MOVABLES.SINUSOID,getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(2*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.sin(b*x-c)+d},getPropsForCoeffs:function(coeffs){return {a:coeffs[0],b:coeffs[1],c:coeffs[2],d:coeffs[3]}},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" sin("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)},areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(canonicalSineCoefficients(coeffs1),canonicalSineCoefficients(coeffs2))}});const Tangent=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/7db80d23c35214f98659fe1cf0765811c1bbfbba.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const a=p2[1]-p1[1];const b=Math.PI/(4*(p2[0]-p1[0]));const c=p1[0]*b;const d=p1[1];return [a,b,c,d]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return a*Math.tan(b*x-c)+d},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];const d=coeffs[3];return "y = "+a.toFixed(3)+" sin("+b.toFixed(3)+"x - "+c.toFixed(3)+") + "+d.toFixed(3)},areEqual:function(coeffs1,coeffs2){return approximateDeepEqual(canonicalTangentCoefficients(coeffs1),canonicalTangentCoefficients(coeffs2))}});const Exponential=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/9cbfad55525e3ce755a31a631b074670a5dad611.png",defaultCoords:[[.5,.55],[.75,.75]],defaultAsymptote:[[0,.5],[1,.5]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=asymptote[0][1];return ___default.default.all(coords,coord=>coord[1]!==y)},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const y=newCoord[1];const isValid=___default.default.all(coords,coord=>coord[1]>y)||___default.default.all(coords,coord=>coord[1]<y);if(isValid){return [oldCoord[0],y]}const oldY=oldCoord[1];const wasBelow=___default.default.all(coords,coord=>coord[1]>oldY);if(wasBelow){const bottomMost=___default.default.min(___default.default.map(coords,coord=>coord[1]));return [oldCoord[0],bottomMost-graph.snapStep[1]]}const topMost=___default.default.max(___default.default.map(coords,coord=>coord[1]));return [oldCoord[0],topMost+graph.snapStep[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const p1=coords[0];const p2=coords[1];const c=asymptote[0][1];const b=Math.log((p1[1]-c)/(p2[1]-c))/(p1[0]-p2[0]);const a=(p1[1]-c)/Math.exp(b*p1[0]);return [a,b,c]},getFunctionForCoeffs:function(coeffs,x){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.exp(b*x)+c},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = "+a.toFixed(3)+"e^("+b.toFixed(3)+"x) + "+c.toFixed(3)}});const Logarithm=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/f6491e99d34af34d924bfe0231728ad912068dc3.png",defaultCoords:[[.55,.5],[.75,.75]],defaultAsymptote:[[.5,0],[.5,1]],extraCoordConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=asymptote[0][0];return ___default.default.all(coords,coord=>coord[0]!==x)&&coords[0][1]!==coords[1][1]},extraAsymptoteConstraint:function(newCoord,oldCoord,coords,asymptote,graph){const x=newCoord[0];const isValid=___default.default.all(coords,coord=>coord[0]>x)||___default.default.all(coords,coord=>coord[0]<x);if(isValid){return [x,oldCoord[1]]}const oldX=oldCoord[0];const wasLeft=___default.default.all(coords,coord=>coord[0]>oldX);if(wasLeft){const leftMost=___default.default.min(___default.default.map(coords,coord=>coord[0]));return [leftMost-graph.snapStep[0],oldCoord[1]]}const rightMost=___default.default.max(___default.default.map(coords,coord=>coord[0]));return [rightMost+graph.snapStep[0],oldCoord[1]]},allowReflectOverAsymptote:true,getCoefficients:function(coords,asymptote){const flip=coord=>[coord[1],coord[0]];const inverseCoeffs=Exponential.getCoefficients(___default.default.map(coords,flip),___default.default.map(asymptote,flip));if(inverseCoeffs){const c=-inverseCoeffs[2]/inverseCoeffs[0];const b=1/inverseCoeffs[0];const a=1/inverseCoeffs[1];return [a,b,c]}},getFunctionForCoeffs:function(coeffs,x,asymptote){const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return a*Math.log(b*x+c)},getEquationString:function(coords,asymptote){if(!asymptote){return null}const coeffs=this.getCoefficients(coords,asymptote);const a=coeffs[0];const b=coeffs[1];const c=coeffs[2];return "y = ln("+a.toFixed(3)+"x + "+b.toFixed(3)+") + "+c.toFixed(3)}});const AbsoluteValue=___default.default.extend({},PlotDefaults,{url:"https://ka-perseus-graphie.s3.amazonaws.com/8256a630175a0cb1d11de223d6de0266daf98721.png",defaultCoords:[[.5,.5],[.75,.75]],getCoefficients:function(coords){const p1=coords[0];const p2=coords[1];const denom=p2[0]-p1[0];const num=p2[1]-p1[1];if(denom===0){return}let m=Math.abs(num/denom);if(p2[1]<p1[1]){m*=-1;}const horizontalOffset=p1[0];const verticalOffset=p1[1];return [m,horizontalOffset,verticalOffset]},getFunctionForCoeffs:function(coeffs,x){const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return m*Math.abs(x-horizontalOffset)+verticalOffset},getEquationString:function(coords){const coeffs=this.getCoefficients(coords);const m=coeffs[0];const horizontalOffset=coeffs[1];const verticalOffset=coeffs[2];return "y = "+m.toFixed(3)+"| x - "+horizontalOffset.toFixed(3)+"| + "+verticalOffset.toFixed(3)}});const functionTypeMapping={linear:Linear,quadratic:Quadratic,sinusoid:Sinusoid,tangent:Tangent,exponential:Exponential,logarithm:Logarithm,absolute_value:AbsoluteValue};const allTypes=___default.default.keys(functionTypeMapping);function functionForType(type){return functionTypeMapping[type]}
454
43
 
455
44
  var grapherUtil = /*#__PURE__*/Object.freeze({
456
45
  __proto__: null,
@@ -459,2580 +48,269 @@ var grapherUtil = /*#__PURE__*/Object.freeze({
459
48
  functionForType: functionForType
460
49
  });
461
50
 
462
- function isRealJSONParse(jsonParse) {
463
- const randomPhrase = buildRandomPhrase();
464
- const randomHintPhrase = buildRandomPhrase();
465
- const randomString = buildRandomString();
466
- const testingObject = JSON.stringify({
467
- answerArea: {
468
- calculator: false,
469
- chi2Table: false,
470
- financialCalculatorMonthlyPayment: false,
471
- financialCalculatorTimeToPayOff: false,
472
- financialCalculatorTotalAmount: false,
473
- periodicTable: false,
474
- periodicTableWithKey: false,
475
- tTable: false,
476
- zTable: false
477
- },
478
- hints: [randomHintPhrase, `=${Math.floor(Math.random() * 50) + 1}`],
479
- itemDataVersion: {
480
- major: 0,
481
- minor: 1
482
- },
483
- question: {
484
- content: `${randomPhrase}`,
485
- images: {},
486
- widgets: {
487
- expression1: {
488
- alignment: "default",
489
- graded: false,
490
- options: {
491
- answerForms: [{
492
- considered: "wrong",
493
- form: false,
494
- key: 0,
495
- simplify: false,
496
- value: `${randomString}`
497
- }],
498
- ariaLabel: "Answer",
499
- buttonSets: ["basic"],
500
- functions: ["f", "g", "h"],
501
- static: true,
502
- times: false,
503
- visibleLabel: "Answer"
504
- },
505
- static: true,
506
- type: "expression",
507
- version: {
508
- major: 1,
509
- minor: 0
510
- }
511
- }
512
- }
513
- }
514
- });
515
- const testJSON = buildTestData(testingObject.replace(/"/g, '\\"'));
516
- const parsedTestJSON = jsonParse(testJSON);
517
- const parsedTestItemData = parsedTestJSON.data.assessmentItem.item.itemData;
518
- return approximateDeepEqual(parsedTestItemData, testingObject);
519
- }
520
- function buildRandomString(capitalize = false) {
521
- let randomString = "";
522
- const randomLength = Math.floor(Math.random() * 8) + 3;
523
- for (let i = 0; i < randomLength; i++) {
524
- const randomLetter = String.fromCharCode(97 + Math.floor(Math.random() * 26));
525
- randomString += capitalize && i === 0 ? randomLetter.toUpperCase() : randomLetter;
526
- }
527
- return randomString;
528
- }
529
- function buildRandomPhrase() {
530
- const phrases = [];
531
- const randomLength = Math.floor(Math.random() * 10) + 5;
532
- for (let i = 0; i < randomLength; i++) {
533
- phrases.push(buildRandomString(i === 0));
534
- }
535
- const modifierStart = ["**", "$"];
536
- const modifierEnd = ["**", "$"];
537
- const modifierIndex = Math.floor(Math.random() * modifierStart.length);
538
- return `${modifierStart[modifierIndex]}${phrases.join(" ")}${modifierEnd[modifierIndex]}`;
539
- }
540
- function buildTestData(testObject) {
541
- return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`;
542
- }
51
+ function isRealJSONParse(jsonParse){const randomPhrase=buildRandomPhrase();const randomHintPhrase=buildRandomPhrase();const randomString=buildRandomString();const testingObject=JSON.stringify({answerArea:{calculator:false,chi2Table:false,financialCalculatorMonthlyPayment:false,financialCalculatorTimeToPayOff:false,financialCalculatorTotalAmount:false,periodicTable:false,periodicTableWithKey:false,tTable:false,zTable:false},hints:[randomHintPhrase,`=${Math.floor(Math.random()*50)+1}`],itemDataVersion:{major:0,minor:1},question:{content:`${randomPhrase}`,images:{},widgets:{expression1:{alignment:"default",graded:false,options:{answerForms:[{considered:"wrong",form:false,key:0,simplify:false,value:`${randomString}`}],ariaLabel:"Answer",buttonSets:["basic"],functions:["f","g","h"],static:true,times:false,visibleLabel:"Answer"},static:true,type:"expression",version:{major:1,minor:0}}}}});const testJSON=buildTestData(testingObject.replace(/"/g,'\\"'));const parsedTestJSON=jsonParse(testJSON);const parsedTestItemData=parsedTestJSON.data.assessmentItem.item.itemData;return approximateDeepEqual(parsedTestItemData,testingObject)}function buildRandomString(capitalize=false){let randomString="";const randomLength=Math.floor(Math.random()*8)+3;for(let i=0;i<randomLength;i++){const randomLetter=String.fromCharCode(97+Math.floor(Math.random()*26));randomString+=capitalize&&i===0?randomLetter.toUpperCase():randomLetter;}return randomString}function buildRandomPhrase(){const phrases=[];const randomLength=Math.floor(Math.random()*10)+5;for(let i=0;i<randomLength;i++){phrases.push(buildRandomString(i===0));}const modifierStart=["**","$"];const modifierEnd=["**","$"];const modifierIndex=Math.floor(Math.random()*modifierStart.length);return `${modifierStart[modifierIndex]}${phrases.join(" ")}${modifierEnd[modifierIndex]}`}function buildTestData(testObject){return `{"data":{"assessmentItem":{"__typename":"AssessmentItemOrError","error":null,"item":{"__typename":"AssessmentItem","id":"x890b3c70f3e8f4a6","itemData":"${testObject}","problemType":"Type 1","sha":"c7284a3ad65214b4e62bccce236d92f7f5d35941"}}}}`}
543
52
 
544
- function success(value) {
545
- return {
546
- type: "success",
547
- value
548
- };
549
- }
550
- function failure(detail) {
551
- return {
552
- type: "failure",
553
- detail
554
- };
555
- }
556
- function isFailure(result) {
557
- return result.type === "failure";
558
- }
559
- function isSuccess(result) {
560
- return result.type === "success";
561
- }
562
- function all(results, combineFailureDetails = a => a) {
563
- const values = [];
564
- const failureDetails = [];
565
- for (const result of results) {
566
- if (result.type === "success") {
567
- values.push(result.value);
568
- } else {
569
- failureDetails.push(result.detail);
570
- }
571
- }
572
- if (failureDetails.length > 0) {
573
- return failure(failureDetails.reduce(combineFailureDetails));
574
- }
575
- return success(values);
576
- }
53
+ function success(value){return {type:"success",value}}function failure(detail){return {type:"failure",detail}}function isFailure(result){return result.type==="failure"}function isSuccess(result){return result.type==="success"}function all(results,combineFailureDetails=a=>a){const values=[];const failureDetails=[];for(const result of results){if(result.type==="success"){values.push(result.value);}else {failureDetails.push(result.detail);}}if(failureDetails.length>0){return failure(failureDetails.reduce(combineFailureDetails))}return success(values)}
577
54
 
578
- class ErrorTrackingParseContext {
579
- constructor(path) {
580
- this.path = path;
581
- }
582
- failure(expected, badValue) {
583
- return failure([{
584
- expected: wrapInArray(expected),
585
- badValue,
586
- path: this.path
587
- }]);
588
- }
589
- forSubtree(key) {
590
- return new ErrorTrackingParseContext([...this.path, key]);
591
- }
592
- success(value) {
593
- return success(value);
594
- }
595
- }
596
- function wrapInArray(a) {
597
- return Array.isArray(a) ? a : [a];
598
- }
55
+ class ErrorTrackingParseContext{failure(expected,badValue){return failure([{expected:wrapInArray(expected),badValue,path:this.path}])}forSubtree(key){return new ErrorTrackingParseContext([...this.path,key])}success(value){return success(value)}constructor(path){this.path=path;}}function wrapInArray(a){return Array.isArray(a)?a:[a]}
599
56
 
600
- function formatPath(path) {
601
- return "(root)" + path.map(formatPathSegment).join("");
602
- }
603
- function formatPathSegment(segment) {
604
- if (typeof segment === "string") {
605
- return validIdentifier.test(segment) ? "." + segment : `[${JSON.stringify(segment)}]`;
606
- }
607
- return `[${segment.toString()}]`;
608
- }
609
- const validIdentifier = /^[A-Za-z$_][A-Za-z$_0-9]*$/;
57
+ function formatPath(path){return "(root)"+path.map(formatPathSegment).join("")}function formatPathSegment(segment){if(typeof segment==="string"){return validIdentifier.test(segment)?"."+segment:`[${JSON.stringify(segment)}]`}return `[${segment.toString()}]`}const validIdentifier=/^[A-Za-z$_][A-Za-z$_0-9]*$/;
610
58
 
611
- function message(failure) {
612
- const expected = conjoin(failure.expected);
613
- const path = formatPath(failure.path);
614
- const badValue = JSON.stringify(failure.badValue);
615
- return `At ${path} -- expected ${expected}, but got ${badValue}`;
616
- }
617
- function conjoin(items) {
618
- switch (items.length) {
619
- case 1:
620
- return items[0];
621
- case 2:
622
- return items.join(" or ");
623
- default:
624
- {
625
- const allButLast = items.slice(0, items.length - 1);
626
- const last = items[items.length - 1];
627
- return allButLast.join(", ") + ", or " + last;
628
- }
629
- }
630
- }
59
+ function message(failure){const expected=conjoin(failure.expected);const path=formatPath(failure.path);const badValue=JSON.stringify(failure.badValue);return `At ${path} -- expected ${expected}, but got ${badValue}`}function conjoin(items){switch(items.length){case 1:return items[0];case 2:return items.join(" or ");default:{const allButLast=items.slice(0,items.length-1);const last=items[items.length-1];return allButLast.join(", ")+", or "+last}}}
631
60
 
632
- function parse(value, parser) {
633
- const result = parser(value, new ErrorTrackingParseContext([]));
634
- if (isFailure(result)) {
635
- return failure(result.detail.map(message).join("; "));
636
- }
637
- return result;
638
- }
61
+ function parse(value,parser){const result=parser(value,new ErrorTrackingParseContext([]));if(isFailure(result)){return failure(result.detail.map(message).join("; "))}return result}
639
62
 
640
- const any = (rawValue, ctx) => ctx.success(rawValue);
63
+ const any=(rawValue,ctx)=>ctx.success(rawValue);
641
64
 
642
- function array(elementParser) {
643
- return (rawValue, ctx) => {
644
- if (!Array.isArray(rawValue)) {
645
- return ctx.failure("array", rawValue);
646
- }
647
- const elementResults = rawValue.map((elem, i) => elementParser(elem, ctx.forSubtree(i)));
648
- return all(elementResults, concat);
649
- };
650
- }
651
- function concat(a, b) {
652
- return [...a, ...b];
653
- }
65
+ function array(elementParser){return (rawValue,ctx)=>{if(!Array.isArray(rawValue)){return ctx.failure("array",rawValue)}const elementResults=rawValue.map((elem,i)=>elementParser(elem,ctx.forSubtree(i)));return all(elementResults,concat)}}function concat(a,b){return [...a,...b]}
654
66
 
655
- function boolean(rawValue, ctx) {
656
- if (typeof rawValue === "boolean") {
657
- return ctx.success(rawValue);
658
- }
659
- return ctx.failure("boolean", rawValue);
660
- }
67
+ function boolean(rawValue,ctx){if(typeof rawValue==="boolean"){return ctx.success(rawValue)}return ctx.failure("boolean",rawValue)}
661
68
 
662
- function constant(acceptedValue) {
663
- return (rawValue, ctx) => {
664
- if (rawValue !== acceptedValue) {
665
- return ctx.failure(String(JSON.stringify(acceptedValue)), rawValue);
666
- }
667
- return ctx.success(acceptedValue);
668
- };
669
- }
69
+ function constant(acceptedValue){return (rawValue,ctx)=>{if(rawValue!==acceptedValue){return ctx.failure(String(JSON.stringify(acceptedValue)),rawValue)}return ctx.success(acceptedValue)}}
670
70
 
671
- function enumeration(...acceptedValues) {
672
- return (rawValue, ctx) => {
673
- if (typeof rawValue === "string") {
674
- const index = acceptedValues.indexOf(rawValue);
675
- if (index > -1) {
676
- return ctx.success(acceptedValues[index]);
677
- }
678
- }
679
- const expected = acceptedValues.map(v => JSON.stringify(v));
680
- return ctx.failure(expected, rawValue);
681
- };
682
- }
71
+ function enumeration(...acceptedValues){return (rawValue,ctx)=>{if(typeof rawValue==="string"){const index=acceptedValues.indexOf(rawValue);if(index>-1){return ctx.success(acceptedValues[index])}}const expected=acceptedValues.map(v=>JSON.stringify(v));return ctx.failure(expected,rawValue)}}
683
72
 
684
- function isObject(x) {
685
- return x != null && Object.getPrototypeOf(x) === Object.prototype;
686
- }
73
+ function isObject(x){return x!=null&&Object.getPrototypeOf(x)===Object.prototype}
687
74
 
688
- function nullable(parseValue) {
689
- return (rawValue, ctx) => {
690
- if (rawValue === null) {
691
- return ctx.success(rawValue);
692
- }
693
- return parseValue(rawValue, ctx);
694
- };
695
- }
75
+ function nullable(parseValue){return (rawValue,ctx)=>{if(rawValue===null){return ctx.success(rawValue)}return parseValue(rawValue,ctx)}}
696
76
 
697
- const number = (rawValue, ctx) => {
698
- if (typeof rawValue === "number") {
699
- return ctx.success(rawValue);
700
- }
701
- return ctx.failure("number", rawValue);
702
- };
703
-
704
- function object(schema) {
705
- return (rawValue, ctx) => {
706
- if (!isObject(rawValue)) {
707
- return ctx.failure("object", rawValue);
708
- }
709
- const ret = _extends({}, rawValue);
710
- const mismatches = [];
711
- for (const [prop, propParser] of Object.entries(schema)) {
712
- const result = propParser(rawValue[prop], ctx.forSubtree(prop));
713
- if (isSuccess(result)) {
714
- if (result.value !== undefined || prop in rawValue) {
715
- ret[prop] = result.value;
716
- }
717
- } else {
718
- mismatches.push(...result.detail);
719
- }
720
- }
721
- if (mismatches.length > 0) {
722
- return failure(mismatches);
723
- }
724
- return ctx.success(ret);
725
- };
726
- }
77
+ const number=(rawValue,ctx)=>{if(typeof rawValue==="number"){return ctx.success(rawValue)}return ctx.failure("number",rawValue)};
727
78
 
728
- function optional(parseValue) {
729
- return (rawValue, ctx) => {
730
- if (rawValue === undefined) {
731
- return ctx.success(rawValue);
732
- }
733
- return parseValue(rawValue, ctx);
734
- };
735
- }
79
+ function object(schema){return (rawValue,ctx)=>{if(!isObject(rawValue)){return ctx.failure("object",rawValue)}const ret={...rawValue};const mismatches=[];for(const[prop,propParser]of Object.entries(schema)){const result=propParser(rawValue[prop],ctx.forSubtree(prop));if(isSuccess(result)){if(result.value!==undefined||prop in rawValue){ret[prop]=result.value;}}else {mismatches.push(...result.detail);}}if(mismatches.length>0){return failure(mismatches)}return ctx.success(ret)}}
736
80
 
737
- function pair(parseA, parseB) {
738
- return (rawValue, ctx) => {
739
- if (!Array.isArray(rawValue)) {
740
- return ctx.failure("array", rawValue);
741
- }
742
- if (rawValue.length !== 2) {
743
- return ctx.failure("array of length 2", rawValue);
744
- }
745
- const [rawA, rawB] = rawValue;
746
- const resultA = parseA(rawA, ctx.forSubtree(0));
747
- if (isFailure(resultA)) {
748
- return resultA;
749
- }
750
- const resultB = parseB(rawB, ctx.forSubtree(1));
751
- if (isFailure(resultB)) {
752
- return resultB;
753
- }
754
- return ctx.success([resultA.value, resultB.value]);
755
- };
756
- }
81
+ function optional(parseValue){return (rawValue,ctx)=>{if(rawValue===undefined){return ctx.success(rawValue)}return parseValue(rawValue,ctx)}}
757
82
 
758
- function pipeParsers(p) {
759
- return new ParserPipeline(p);
760
- }
761
- class ParserPipeline {
762
- constructor(parser) {
763
- this.parser = parser;
764
- }
765
- then(nextParser) {
766
- return new ParserPipeline(composeParsers(this.parser, nextParser));
767
- }
768
- }
769
- function composeParsers(parserA, parserB) {
770
- return (rawValue, ctx) => {
771
- const partialResult = parserA(rawValue, ctx);
772
- if (isFailure(partialResult)) {
773
- return partialResult;
774
- }
775
- return parserB(partialResult.value, ctx);
776
- };
777
- }
83
+ function pair(parseA,parseB){return (rawValue,ctx)=>{if(!Array.isArray(rawValue)){return ctx.failure("array",rawValue)}if(rawValue.length!==2){return ctx.failure("array of length 2",rawValue)}const[rawA,rawB]=rawValue;const resultA=parseA(rawA,ctx.forSubtree(0));if(isFailure(resultA)){return resultA}const resultB=parseB(rawB,ctx.forSubtree(1));if(isFailure(resultB)){return resultB}return ctx.success([resultA.value,resultB.value])}}
778
84
 
779
- function record(parseKey, parseValue) {
780
- return (rawValue, ctx) => {
781
- if (!isObject(rawValue)) {
782
- return ctx.failure("object", rawValue);
783
- }
784
- const result = {};
785
- const mismatches = [];
786
- for (const [key, value] of Object.entries(rawValue)) {
787
- const entryCtx = ctx.forSubtree(key);
788
- const keyResult = parseKey(key, entryCtx);
789
- if (isFailure(keyResult)) {
790
- mismatches.push(...keyResult.detail);
791
- }
792
- const valueResult = parseValue(value, entryCtx);
793
- if (isFailure(valueResult)) {
794
- mismatches.push(...valueResult.detail);
795
- }
796
- if (isSuccess(keyResult) && isSuccess(valueResult)) {
797
- result[keyResult.value] = valueResult.value;
798
- }
799
- }
800
- if (mismatches.length > 0) {
801
- return failure(mismatches);
802
- }
803
- return ctx.success(result);
804
- };
805
- }
85
+ function pipeParsers(p){return new ParserPipeline(p)}class ParserPipeline{then(nextParser){return new ParserPipeline(composeParsers(this.parser,nextParser))}constructor(parser){this.parser=parser;}}function composeParsers(parserA,parserB){return (rawValue,ctx)=>{const partialResult=parserA(rawValue,ctx);if(isFailure(partialResult)){return partialResult}return parserB(partialResult.value,ctx)}}
806
86
 
807
- const string = (rawValue, ctx) => {
808
- if (typeof rawValue === "string") {
809
- return ctx.success(rawValue);
810
- }
811
- return ctx.failure("string", rawValue);
812
- };
813
-
814
- function trio(parseA, parseB, parseC) {
815
- return (rawValue, ctx) => {
816
- if (!Array.isArray(rawValue)) {
817
- return ctx.failure("array", rawValue);
818
- }
819
- if (rawValue.length !== 3) {
820
- return ctx.failure("array of length 3", rawValue);
821
- }
822
- const resultA = parseA(rawValue[0], ctx.forSubtree(0));
823
- if (isFailure(resultA)) {
824
- return resultA;
825
- }
826
- const resultB = parseB(rawValue[1], ctx.forSubtree(1));
827
- if (isFailure(resultB)) {
828
- return resultB;
829
- }
830
- const resultC = parseC(rawValue[2], ctx.forSubtree(2));
831
- if (isFailure(resultC)) {
832
- return resultC;
833
- }
834
- return ctx.success([resultA.value, resultB.value, resultC.value]);
835
- };
836
- }
87
+ function record(parseKey,parseValue){return (rawValue,ctx)=>{if(!isObject(rawValue)){return ctx.failure("object",rawValue)}const result={};const mismatches=[];for(const[key,value]of Object.entries(rawValue)){const entryCtx=ctx.forSubtree(key);const keyResult=parseKey(key,entryCtx);if(isFailure(keyResult)){mismatches.push(...keyResult.detail);}const valueResult=parseValue(value,entryCtx);if(isFailure(valueResult)){mismatches.push(...valueResult.detail);}if(isSuccess(keyResult)&&isSuccess(valueResult)){result[keyResult.value]=valueResult.value;}}if(mismatches.length>0){return failure(mismatches)}return ctx.success(result)}}
837
88
 
838
- function union(parseBranch) {
839
- return new UnionBuilder(parseBranch);
840
- }
841
- class UnionBuilder {
842
- constructor(parser) {
843
- this.parser = parser;
844
- }
845
- or(newBranch) {
846
- return new UnionBuilder(either(this.parser, newBranch));
847
- }
848
- }
849
- function either(parseA, parseB) {
850
- return (rawValue, ctx) => {
851
- const resultA = parseA(rawValue, ctx);
852
- if (isSuccess(resultA)) {
853
- return resultA;
854
- }
855
- return parseB(rawValue, ctx);
856
- };
857
- }
89
+ const string=(rawValue,ctx)=>{if(typeof rawValue==="string"){return ctx.success(rawValue)}return ctx.failure("string",rawValue)};
858
90
 
859
- function defaulted(parser, fallback) {
860
- return (rawValue, ctx) => {
861
- if (rawValue == null) {
862
- return success(fallback(rawValue));
863
- }
864
- return parser(rawValue, ctx);
865
- };
866
- }
91
+ function trio(parseA,parseB,parseC){return (rawValue,ctx)=>{if(!Array.isArray(rawValue)){return ctx.failure("array",rawValue)}if(rawValue.length!==3){return ctx.failure("array of length 3",rawValue)}const resultA=parseA(rawValue[0],ctx.forSubtree(0));if(isFailure(resultA)){return resultA}const resultB=parseB(rawValue[1],ctx.forSubtree(1));if(isFailure(resultB)){return resultB}const resultC=parseC(rawValue[2],ctx.forSubtree(2));if(isFailure(resultC)){return resultC}return ctx.success([resultA.value,resultB.value,resultC.value])}}
867
92
 
868
- const parseImages = defaulted(record(string, object({
869
- width: number,
870
- height: number
871
- })), () => ({}));
872
-
873
- function parseWidget(parseType, parseOptions) {
874
- return object({
875
- type: parseType,
876
- static: optional(boolean),
877
- graded: optional(boolean),
878
- alignment: optional(string),
879
- options: parseOptions,
880
- key: optional(nullable(number)),
881
- version: optional(object({
882
- major: number,
883
- minor: number
884
- }))
885
- });
886
- }
887
- function parseWidgetWithVersion(parseVersion, parseType, parseOptions) {
888
- return object({
889
- type: parseType,
890
- static: optional(boolean),
891
- graded: optional(boolean),
892
- alignment: optional(string),
893
- options: parseOptions,
894
- key: optional(nullable(number)),
895
- version: parseVersion
896
- });
897
- }
93
+ function union(parseBranch){return new UnionBuilder(parseBranch)}class UnionBuilder{or(newBranch){return new UnionBuilder(either(this.parser,newBranch))}constructor(parser){this.parser=parser;}}function either(parseA,parseB){return (rawValue,ctx)=>{const resultA=parseA(rawValue,ctx);if(isSuccess(resultA)){return resultA}return parseB(rawValue,ctx)}}
898
94
 
899
- const parseCategorizerWidget = parseWidget(constant("categorizer"), object({
900
- items: array(string),
901
- categories: array(string),
902
- randomizeItems: defaulted(boolean, () => false),
903
- static: defaulted(boolean, () => false),
904
- values: array(defaulted(number, () => 0)),
905
- highlightLint: optional(boolean),
906
- linterContext: optional(object({
907
- contentType: string,
908
- paths: array(string),
909
- stack: array(string)
910
- }))
911
- }));
912
-
913
- const parseCSProgramWidget = parseWidget(constant("cs-program"), object({
914
- programID: string,
915
- programType: any,
916
- settings: array(object({
917
- name: string,
918
- value: string
919
- })),
920
- showEditor: boolean,
921
- showButtons: boolean,
922
- height: number,
923
- static: defaulted(boolean, () => false)
924
- }));
925
-
926
- const parseDefinitionWidget = parseWidget(constant("definition"), object({
927
- togglePrompt: string,
928
- definition: string,
929
- static: defaulted(boolean, () => false)
930
- }));
931
-
932
- const parseDropdownWidget = parseWidget(constant("dropdown"), object({
933
- placeholder: defaulted(string, () => ""),
934
- ariaLabel: optional(string),
935
- visibleLabel: optional(string),
936
- static: defaulted(boolean, () => false),
937
- choices: array(object({
938
- content: string,
939
- correct: boolean
940
- }))
941
- }));
942
-
943
- const parseExplanationWidget = parseWidget(constant("explanation"), object({
944
- showPrompt: string,
945
- hidePrompt: string,
946
- explanation: string,
947
- widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
948
- static: defaulted(boolean, () => false)
949
- }));
950
-
951
- const KeypadKeys = ["PLUS", "MINUS", "NEGATIVE", "TIMES", "DIVIDE", "DECIMAL", "PERIOD", "PERCENT", "CDOT", "EQUAL", "NEQ", "GT", "LT", "GEQ", "LEQ", "FRAC_INCLUSIVE", "FRAC_EXCLUSIVE", "FRAC", "EXP", "EXP_2", "EXP_3", "SQRT", "CUBE_ROOT", "RADICAL", "LEFT_PAREN", "RIGHT_PAREN", "LN", "LOG", "LOG_N", "SIN", "COS", "TAN", "PI", "THETA", "UP", "RIGHT", "DOWN", "LEFT", "BACKSPACE", "DISMISS", "JUMP_OUT_PARENTHESES", "JUMP_OUT_EXPONENT", "JUMP_OUT_BASE", "JUMP_INTO_NUMERATOR", "JUMP_OUT_NUMERATOR", "JUMP_OUT_DENOMINATOR", "NUM_0", "NUM_1", "NUM_2", "NUM_3", "NUM_4", "NUM_5", "NUM_6", "NUM_7", "NUM_8", "NUM_9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
952
-
953
- function deriveExtraKeys(widgetOptions) {
954
- if (widgetOptions.extraKeys) {
955
- return widgetOptions.extraKeys;
956
- }
957
- const defaultKeys = ["PI"];
958
- if (widgetOptions.answerForms == null) {
959
- return defaultKeys;
960
- }
961
- const uniqueExtraVariables = {};
962
- const uniqueExtraConstants = {};
963
- for (const answerForm of widgetOptions.answerForms) {
964
- const maybeExpr = KAS.parse(answerForm.value, widgetOptions);
965
- if (maybeExpr.parsed) {
966
- const expr = maybeExpr.expr;
967
- const isGreek = symbol => symbol === "pi" || symbol === "theta";
968
- const toKey = symbol => isGreek(symbol) ? symbol.toUpperCase() : symbol;
969
- const isKey = key => KeypadKeys.includes(key);
970
- for (const variable of expr.getVars()) {
971
- const maybeKey = toKey(variable);
972
- if (isKey(maybeKey)) {
973
- uniqueExtraVariables[maybeKey] = true;
974
- }
975
- }
976
- for (const constant of expr.getConsts()) {
977
- const maybeKey = toKey(constant);
978
- if (isKey(maybeKey)) {
979
- uniqueExtraConstants[maybeKey] = true;
980
- }
981
- }
982
- }
983
- }
984
- const extraVariables = Object.keys(uniqueExtraVariables).sort();
985
- const extraConstants = Object.keys(uniqueExtraConstants).sort();
986
- const extraKeys = [...extraVariables, ...extraConstants];
987
- if (!extraKeys.length) {
988
- return defaultKeys;
989
- }
990
- return extraKeys;
991
- }
95
+ function defaulted(parser,fallback){return (rawValue,ctx)=>{if(rawValue==null){return success(fallback(rawValue))}return parser(rawValue,ctx)}}
992
96
 
993
- function convert(f) {
994
- return (rawValue, ctx) => ctx.success(f(rawValue));
995
- }
97
+ const parseImages=defaulted(record(string,object({width:number,height:number})),()=>({}));
996
98
 
997
- const parseLegacyButtonSet = enumeration("basic", "basic+div", "trig", "prealgebra", "logarithms", "basic relations", "advanced relations", "scientific");
998
- const parseLegacyButtonSets = defaulted(array(parseLegacyButtonSet), () => ["basic", "trig", "prealgebra", "logarithms"]);
99
+ function parseWidget(parseType,parseOptions){return object({type:parseType,static:optional(boolean),graded:optional(boolean),alignment:optional(string),options:parseOptions,key:optional(nullable(number)),version:optional(object({major:number,minor:number}))})}function parseWidgetWithVersion(parseVersion,parseType,parseOptions){return object({type:parseType,static:optional(boolean),graded:optional(boolean),alignment:optional(string),options:parseOptions,key:optional(nullable(number)),version:parseVersion})}
999
100
 
1000
- function versionedWidgetOptions(latestMajorVersion, parseLatest) {
1001
- return new VersionedWidgetOptionsParserBuilder(latestMajorVersion, parseLatest, latest => latest, (raw, ctx) => ctx.failure("widget options with a known version number", raw));
1002
- }
1003
- class VersionedWidgetOptionsParserBuilder {
1004
- constructor(majorVersion, parseThisVersion, migrateToLatest, parseOtherVersions) {
1005
- this.parser = void 0;
1006
- this.migrateToLatest = migrateToLatest;
1007
- this.parseOtherVersions = parseOtherVersions;
1008
- const parseThisVersionAndMigrateToLatest = pipeParsers(parseThisVersion).then(convert(this.migrateToLatest)).parser;
1009
- this.parser = (raw, ctx) => {
1010
- if (!isObject(raw)) {
1011
- return ctx.failure("object", raw);
1012
- }
1013
- const versionParseResult = parseVersionedObject(raw, ctx);
1014
- if (isFailure(versionParseResult)) {
1015
- return versionParseResult;
1016
- }
1017
- if (versionParseResult.value.version.major !== majorVersion) {
1018
- return this.parseOtherVersions(raw, ctx);
1019
- }
1020
- return parseThisVersionAndMigrateToLatest(raw, ctx);
1021
- };
1022
- }
1023
- withMigrationFrom(majorVersion, parseOldVersion, migrateToNextVersion) {
1024
- const parseOtherVersions = this.parser;
1025
- const migrateToLatest = old => this.migrateToLatest(migrateToNextVersion(old));
1026
- return new VersionedWidgetOptionsParserBuilder(majorVersion, parseOldVersion, migrateToLatest, parseOtherVersions);
1027
- }
1028
- }
1029
- const parseVersionedObject = object({
1030
- version: defaulted(object({
1031
- major: number,
1032
- minor: number
1033
- }), () => ({
1034
- major: 0,
1035
- minor: 0
1036
- }))
1037
- });
101
+ const parseCategorizerWidget=parseWidget(constant("categorizer"),object({items:array(string),categories:array(string),randomizeItems:defaulted(boolean,()=>false),static:defaulted(boolean,()=>false),values:array(defaulted(number,()=>0)),highlightLint:optional(boolean),linterContext:optional(object({contentType:string,paths:array(string),stack:array(string)}))}));
1038
102
 
1039
- const stringOrNumberOrNullOrUndefined = union(string).or(number).or(constant(null)).or(constant(undefined)).parser;
1040
- const parsePossiblyInvalidAnswerForm = object({
1041
- value: optional(string),
1042
- form: defaulted(boolean, () => false),
1043
- simplify: defaulted(boolean, () => false),
1044
- considered: enumeration("correct", "wrong", "ungraded"),
1045
- key: pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(String)).parser
1046
- });
1047
- function removeInvalidAnswerForms(possiblyInvalid) {
1048
- const valid = [];
1049
- for (const answerForm of possiblyInvalid) {
1050
- const {
1051
- value
1052
- } = answerForm;
1053
- if (value != null) {
1054
- valid.push(_extends({}, answerForm, {
1055
- value
1056
- }));
1057
- }
1058
- }
1059
- return valid;
1060
- }
1061
- const version2$1 = object({
1062
- major: constant(2),
1063
- minor: number
1064
- });
1065
- const parseExpressionWidgetV2 = parseWidgetWithVersion(version2$1, constant("expression"), object({
1066
- answerForms: pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,
1067
- functions: array(string),
1068
- times: boolean,
1069
- visibleLabel: optional(string),
1070
- ariaLabel: optional(string),
1071
- buttonSets: parseLegacyButtonSets,
1072
- buttonsVisible: optional(enumeration("always", "never", "focused")),
1073
- extraKeys: array(enumeration(...KeypadKeys))
1074
- }));
1075
- const version1$1 = object({
1076
- major: constant(1),
1077
- minor: number
1078
- });
1079
- const parseExpressionWidgetV1 = parseWidgetWithVersion(version1$1, constant("expression"), object({
1080
- answerForms: pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,
1081
- functions: array(string),
1082
- times: boolean,
1083
- visibleLabel: optional(string),
1084
- ariaLabel: optional(string),
1085
- buttonSets: parseLegacyButtonSets,
1086
- buttonsVisible: optional(enumeration("always", "never", "focused"))
1087
- }));
1088
- function migrateV1ToV2$1(widget) {
1089
- const {
1090
- options
1091
- } = widget;
1092
- return _extends({}, widget, {
1093
- version: {
1094
- major: 2,
1095
- minor: 0
1096
- },
1097
- options: {
1098
- times: options.times,
1099
- buttonSets: options.buttonSets,
1100
- functions: options.functions,
1101
- buttonsVisible: options.buttonsVisible,
1102
- visibleLabel: options.visibleLabel,
1103
- ariaLabel: options.ariaLabel,
1104
- answerForms: options.answerForms,
1105
- extraKeys: deriveExtraKeys(options)
1106
- }
1107
- });
1108
- }
1109
- const version0$1 = optional(object({
1110
- major: constant(0),
1111
- minor: number
1112
- }));
1113
- const parseExpressionWidgetV0 = parseWidgetWithVersion(version0$1, constant("expression"), object({
1114
- functions: array(string),
1115
- times: boolean,
1116
- visibleLabel: optional(string),
1117
- ariaLabel: optional(string),
1118
- form: boolean,
1119
- simplify: boolean,
1120
- value: string,
1121
- buttonSets: parseLegacyButtonSets,
1122
- buttonsVisible: optional(enumeration("always", "never", "focused"))
1123
- }));
1124
- function migrateV0ToV1$1(widget) {
1125
- const {
1126
- options
1127
- } = widget;
1128
- return _extends({}, widget, {
1129
- version: {
1130
- major: 1,
1131
- minor: 0
1132
- },
1133
- options: {
1134
- times: options.times,
1135
- buttonSets: options.buttonSets,
1136
- functions: options.functions,
1137
- buttonsVisible: options.buttonsVisible,
1138
- visibleLabel: options.visibleLabel,
1139
- ariaLabel: options.ariaLabel,
1140
- answerForms: [{
1141
- considered: "correct",
1142
- form: options.form,
1143
- simplify: options.simplify,
1144
- value: options.value
1145
- }]
1146
- }
1147
- });
1148
- }
1149
- const parseExpressionWidget = versionedWidgetOptions(2, parseExpressionWidgetV2).withMigrationFrom(1, parseExpressionWidgetV1, migrateV1ToV2$1).withMigrationFrom(0, parseExpressionWidgetV0, migrateV0ToV1$1).parser;
1150
-
1151
- const falseToNull = pipeParsers(constant(false)).then(convert(() => null)).parser;
1152
- const parseGradedGroupWidgetOptions = object({
1153
- title: defaulted(string, () => ""),
1154
- hasHint: optional(nullable(boolean)),
1155
- hint: union(falseToNull).or(constant(null)).or(constant(undefined)).or((rawVal, ctx) => parsePerseusRenderer(rawVal, ctx)).parser,
1156
- content: string,
1157
- widgets: (rawVal, ctx) => parseWidgetsMap(rawVal, ctx),
1158
- widgetEnabled: optional(nullable(boolean)),
1159
- immutableWidgets: optional(nullable(boolean)),
1160
- images: record(string, object({
1161
- width: number,
1162
- height: number
1163
- }))
1164
- });
1165
- const parseGradedGroupWidget = parseWidget(constant("graded-group"), parseGradedGroupWidgetOptions);
103
+ const parseCSProgramWidget=parseWidget(constant("cs-program"),object({programID:string,programType:any,settings:array(object({name:string,value:string})),showEditor:boolean,showButtons:boolean,height:number,static:defaulted(boolean,()=>false)}));
1166
104
 
1167
- const parseGradedGroupSetWidget = parseWidget(constant("graded-group-set"), object({
1168
- gradedGroups: array(parseGradedGroupWidgetOptions)
1169
- }));
105
+ const parseDefinitionWidget=parseWidget(constant("definition"),object({togglePrompt:string,definition:string,static:defaulted(boolean,()=>false)}));
1170
106
 
1171
- function discriminatedUnionOn(discriminantKey) {
1172
- const noMoreBranches = (raw, ctx) => {
1173
- if (!isObject(raw)) {
1174
- return ctx.failure("object", raw);
1175
- }
1176
- return ctx.forSubtree(discriminantKey).failure("a valid value", raw[discriminantKey]);
1177
- };
1178
- return new DiscriminatedUnionBuilder(discriminantKey, noMoreBranches);
1179
- }
1180
- class DiscriminatedUnionBuilder {
1181
- constructor(discriminantKey, parser) {
1182
- this.discriminantKey = discriminantKey;
1183
- this.parser = parser;
1184
- }
1185
- withBranch(discriminantValue, parseNewVariant) {
1186
- const parseNewBranch = discriminatedUnionBranch(this.discriminantKey, discriminantValue, parseNewVariant, this.parser);
1187
- return new DiscriminatedUnionBuilder(this.discriminantKey, parseNewBranch);
1188
- }
1189
- }
1190
- function discriminatedUnionBranch(discriminantKey, discriminantValue, parseVariant, parseOtherBranches) {
1191
- return (raw, ctx) => {
1192
- if (!isObject(raw)) {
1193
- return ctx.failure("object", raw);
1194
- }
1195
- if (raw[discriminantKey] === discriminantValue) {
1196
- return parseVariant(raw, ctx);
1197
- }
1198
- return parseOtherBranches(raw, ctx);
1199
- };
1200
- }
107
+ const parseDropdownWidget=parseWidget(constant("dropdown"),object({placeholder:defaulted(string,()=>""),ariaLabel:optional(string),visibleLabel:optional(string),static:defaulted(boolean,()=>false),choices:array(object({content:string,correct:boolean}))}));
1201
108
 
1202
- const pairOfNumbers$3 = pair(number, number);
1203
- const pairOfPoints = pair(pairOfNumbers$3, pairOfNumbers$3);
1204
- const parseGrapherWidget = parseWidget(constant("grapher"), object({
1205
- availableTypes: array(enumeration("absolute_value", "exponential", "linear", "logarithm", "quadratic", "sinusoid", "tangent")),
1206
- correct: discriminatedUnionOn("type").withBranch("absolute_value", object({
1207
- type: constant("absolute_value"),
1208
- coords: nullable(pairOfPoints)
1209
- })).withBranch("exponential", object({
1210
- type: constant("exponential"),
1211
- asymptote: pairOfPoints,
1212
- coords: nullable(pairOfPoints)
1213
- })).withBranch("linear", object({
1214
- type: constant("linear"),
1215
- coords: nullable(pairOfPoints)
1216
- })).withBranch("logarithm", object({
1217
- type: constant("logarithm"),
1218
- asymptote: pairOfPoints,
1219
- coords: nullable(pairOfPoints)
1220
- })).withBranch("quadratic", object({
1221
- type: constant("quadratic"),
1222
- coords: nullable(pairOfPoints)
1223
- })).withBranch("sinusoid", object({
1224
- type: constant("sinusoid"),
1225
- coords: nullable(pairOfPoints)
1226
- })).withBranch("tangent", object({
1227
- type: constant("tangent"),
1228
- coords: nullable(pairOfPoints)
1229
- })).parser,
1230
- graph: object({
1231
- backgroundImage: object({
1232
- bottom: optional(number),
1233
- height: optional(number),
1234
- left: optional(number),
1235
- scale: optional(number),
1236
- url: optional(nullable(string)),
1237
- width: optional(number)
1238
- }),
1239
- box: optional(pairOfNumbers$3),
1240
- editableSettings: optional(array(enumeration("graph", "snap", "image", "measure"))),
1241
- gridStep: optional(pairOfNumbers$3),
1242
- labels: pair(string, string),
1243
- markings: enumeration("graph", "none", "grid"),
1244
- range: pair(pairOfNumbers$3, pairOfNumbers$3),
1245
- rulerLabel: constant(""),
1246
- rulerTicks: number,
1247
- showProtractor: optional(boolean),
1248
- showRuler: optional(boolean),
1249
- showTooltips: optional(boolean),
1250
- snapStep: optional(pairOfNumbers$3),
1251
- step: pairOfNumbers$3,
1252
- valid: optional(union(boolean).or(string).parser)
1253
- })
1254
- }));
1255
-
1256
- const parseGroupWidget = parseWidget(constant("group"), (rawVal, ctx) => parsePerseusRenderer(rawVal, ctx));
1257
-
1258
- const parseIframeWidget = parseWidget(constant("iframe"), object({
1259
- url: string,
1260
- settings: optional(array(object({
1261
- name: string,
1262
- value: string
1263
- }))),
1264
- width: union(number).or(string).parser,
1265
- height: union(number).or(string).parser,
1266
- allowFullScreen: defaulted(boolean, () => false),
1267
- allowTopNavigation: optional(boolean),
1268
- static: defaulted(boolean, () => false)
1269
- }));
1270
-
1271
- const stringToNumber = (rawValue, ctx) => {
1272
- if (typeof rawValue === "number") {
1273
- return ctx.success(rawValue);
1274
- }
1275
- const parsedNumber = +rawValue;
1276
- if (rawValue === "" || isNaN(parsedNumber)) {
1277
- return ctx.failure("a number or numeric string", rawValue);
1278
- }
1279
- return ctx.success(parsedNumber);
1280
- };
1281
-
1282
- function emptyToZero(x) {
1283
- return x === "" ? 0 : x;
1284
- }
1285
- const imageDimensionToNumber = pipeParsers(union(number).or(string).parser).then(convert(emptyToZero)).then(stringToNumber).parser;
1286
- const dimensionOrUndefined = defaulted(imageDimensionToNumber, () => undefined);
1287
- const parsePerseusImageBackground = object({
1288
- url: optional(nullable(string)),
1289
- width: dimensionOrUndefined,
1290
- height: dimensionOrUndefined,
1291
- top: dimensionOrUndefined,
1292
- left: dimensionOrUndefined,
1293
- bottom: dimensionOrUndefined,
1294
- scale: dimensionOrUndefined
1295
- });
109
+ const parseExplanationWidget=parseWidget(constant("explanation"),object({showPrompt:string,hidePrompt:string,explanation:string,widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>({})),static:defaulted(boolean,()=>false)}));
1296
110
 
1297
- const pairOfNumbers$2 = pair(number, number);
1298
- const parseImageWidget = parseWidget(constant("image"), object({
1299
- title: optional(string),
1300
- caption: optional(string),
1301
- alt: optional(string),
1302
- backgroundImage: parsePerseusImageBackground,
1303
- static: optional(boolean),
1304
- labels: optional(array(object({
1305
- content: string,
1306
- alignment: string,
1307
- coordinates: array(number)
1308
- }))),
1309
- range: optional(pair(pairOfNumbers$2, pairOfNumbers$2)),
1310
- box: optional(pairOfNumbers$2)
1311
- }));
1312
-
1313
- const booleanToString = (rawValue, ctx) => {
1314
- if (typeof rawValue === "boolean") {
1315
- return ctx.success(String(rawValue));
1316
- }
1317
- return ctx.failure("boolean", rawValue);
1318
- };
1319
- const parseInputNumberWidget = parseWidget(constant("input-number"), object({
1320
- answerType: optional(enumeration("number", "decimal", "integer", "rational", "improper", "mixed", "percent", "pi")),
1321
- inexact: optional(boolean),
1322
- maxError: optional(union(number).or(string).parser),
1323
- rightAlign: optional(boolean),
1324
- simplify: enumeration("required", "optional", "enforced"),
1325
- size: enumeration("normal", "small"),
1326
- value: union(number).or(string).or(booleanToString).parser,
1327
- customKeypad: optional(boolean)
1328
- }));
1329
-
1330
- const pairOfNumbers$1 = pair(number, number);
1331
- const stringOrEmpty = defaulted(string, () => "");
1332
- const parseKey = pipeParsers(optional(string)).then(convert(String)).parser;
1333
- const parseFunctionElement = object({
1334
- type: constant("function"),
1335
- key: parseKey,
1336
- options: object({
1337
- value: string,
1338
- funcName: string,
1339
- rangeMin: string,
1340
- rangeMax: string,
1341
- color: string,
1342
- strokeDasharray: string,
1343
- strokeWidth: number
1344
- })
1345
- });
1346
- const parseLabelElement = object({
1347
- type: constant("label"),
1348
- key: parseKey,
1349
- options: object({
1350
- label: string,
1351
- color: string,
1352
- coordX: string,
1353
- coordY: string
1354
- })
1355
- });
1356
- const parseLineElement = object({
1357
- type: constant("line"),
1358
- key: parseKey,
1359
- options: object({
1360
- color: string,
1361
- startX: string,
1362
- startY: string,
1363
- endX: string,
1364
- endY: string,
1365
- strokeDasharray: string,
1366
- strokeWidth: number,
1367
- arrows: string
1368
- })
1369
- });
1370
- const parseMovableLineElement = object({
1371
- type: constant("movable-line"),
1372
- key: parseKey,
1373
- options: object({
1374
- startX: string,
1375
- startY: string,
1376
- startSubscript: number,
1377
- endX: string,
1378
- endY: string,
1379
- endSubscript: number,
1380
- constraint: string,
1381
- snap: number,
1382
- constraintFn: string,
1383
- constraintXMin: string,
1384
- constraintXMax: string,
1385
- constraintYMin: string,
1386
- constraintYMax: string
1387
- })
1388
- });
1389
- const parseMovablePointElement = object({
1390
- type: constant("movable-point"),
1391
- key: parseKey,
1392
- options: object({
1393
- startX: string,
1394
- startY: string,
1395
- varSubscript: number,
1396
- constraint: string,
1397
- snap: number,
1398
- constraintFn: string,
1399
- constraintXMin: stringOrEmpty,
1400
- constraintXMax: stringOrEmpty,
1401
- constraintYMin: stringOrEmpty,
1402
- constraintYMax: stringOrEmpty
1403
- })
1404
- });
1405
- const parseParametricElement = object({
1406
- type: constant("parametric"),
1407
- key: parseKey,
1408
- options: object({
1409
- x: string,
1410
- y: string,
1411
- rangeMin: string,
1412
- rangeMax: string,
1413
- color: string,
1414
- strokeDasharray: string,
1415
- strokeWidth: number
1416
- })
1417
- });
1418
- const parsePointElement = object({
1419
- type: constant("point"),
1420
- key: parseKey,
1421
- options: object({
1422
- color: string,
1423
- coordX: string,
1424
- coordY: string
1425
- })
1426
- });
1427
- const parseRectangleElement = object({
1428
- type: constant("rectangle"),
1429
- key: parseKey,
1430
- options: object({
1431
- color: string,
1432
- coordX: string,
1433
- coordY: string,
1434
- width: string,
1435
- height: string
1436
- })
1437
- });
1438
- const parseInteractionWidget = parseWidget(constant("interaction"), object({
1439
- static: defaulted(boolean, () => false),
1440
- graph: object({
1441
- editableSettings: optional(array(enumeration("canvas", "graph"))),
1442
- box: pairOfNumbers$1,
1443
- labels: array(string),
1444
- range: pair(pairOfNumbers$1, pairOfNumbers$1),
1445
- gridStep: pairOfNumbers$1,
1446
- markings: enumeration("graph", "grid", "none"),
1447
- snapStep: optional(pairOfNumbers$1),
1448
- valid: optional(union(boolean).or(string).parser),
1449
- backgroundImage: optional(parsePerseusImageBackground),
1450
- showProtractor: optional(boolean),
1451
- showRuler: optional(boolean),
1452
- rulerLabel: optional(string),
1453
- rulerTicks: optional(number),
1454
- tickStep: pairOfNumbers$1
1455
- }),
1456
- elements: array(discriminatedUnionOn("type").withBranch("function", parseFunctionElement).withBranch("label", parseLabelElement).withBranch("line", parseLineElement).withBranch("movable-line", parseMovableLineElement).withBranch("movable-point", parseMovablePointElement).withBranch("parametric", parseParametricElement).withBranch("point", parsePointElement).withBranch("rectangle", parseRectangleElement).parser)
1457
- }));
1458
-
1459
- const ItemExtras = ["calculator", "chi2Table", "financialCalculatorMonthlyPayment", "financialCalculatorTotalAmount", "financialCalculatorTimeToPayOff", "periodicTable", "periodicTableWithKey", "tTable", "zTable"];
1460
- const PerseusExpressionAnswerFormConsidered = ["correct", "wrong", "ungraded"];
1461
- const lockedFigureColorNames = ["blue", "green", "grayH", "purple", "pink", "orange", "red"];
1462
- const lockedFigureColors = {
1463
- blue: "#3D7586",
1464
- green: "#447A53",
1465
- grayH: "#3B3D45",
1466
- purple: "#594094",
1467
- pink: "#B25071",
1468
- red: "#D92916",
1469
- orange: "#946700"
1470
- };
1471
- const lockedFigureFillStyles = {
1472
- none: 0,
1473
- white: 1,
1474
- translucent: 0.4,
1475
- solid: 1
1476
- };
1477
- const plotterPlotTypes = ["bar", "line", "pic", "histogram", "dotplot"];
1478
-
1479
- const pairOfNumbers = pair(number, number);
1480
- const parsePerseusGraphTypeAngle = object({
1481
- type: constant("angle"),
1482
- showAngles: optional(boolean),
1483
- allowReflexAngles: optional(boolean),
1484
- angleOffsetDeg: optional(number),
1485
- snapDegrees: optional(number),
1486
- match: optional(constant("congruent")),
1487
- coords: optional(trio(pairOfNumbers, pairOfNumbers, pairOfNumbers)),
1488
- startCoords: optional(trio(pairOfNumbers, pairOfNumbers, pairOfNumbers))
1489
- });
1490
- const parsePerseusGraphTypeCircle = object({
1491
- type: constant("circle"),
1492
- center: optional(pairOfNumbers),
1493
- radius: optional(number),
1494
- startCoords: optional(object({
1495
- center: pairOfNumbers,
1496
- radius: number
1497
- })),
1498
- coord: optional(pairOfNumbers)
1499
- });
1500
- const parsePerseusGraphTypeLinear = object({
1501
- type: constant("linear"),
1502
- coords: optional(nullable(pair(pairOfNumbers, pairOfNumbers))),
1503
- startCoords: optional(pair(pairOfNumbers, pairOfNumbers)),
1504
- coord: optional(pairOfNumbers)
1505
- });
1506
- const parsePerseusGraphTypeLinearSystem = object({
1507
- type: constant("linear-system"),
1508
- coords: optional(nullable(array(pair(pairOfNumbers, pairOfNumbers)))),
1509
- startCoords: optional(array(pair(pairOfNumbers, pairOfNumbers))),
1510
- coord: optional(pairOfNumbers)
1511
- });
1512
- const parsePerseusGraphTypeNone = object({
1513
- type: constant("none")
1514
- });
1515
- const parsePerseusGraphTypePoint = object({
1516
- type: constant("point"),
1517
- numPoints: optional(union(number).or(constant("unlimited")).parser),
1518
- coords: optional(nullable(array(pairOfNumbers))),
1519
- startCoords: optional(array(pairOfNumbers)),
1520
- coord: optional(pairOfNumbers)
1521
- });
1522
- const parsePerseusGraphTypePolygon = object({
1523
- type: constant("polygon"),
1524
- numSides: optional(union(number).or(constant("unlimited")).parser),
1525
- showAngles: optional(boolean),
1526
- showSides: optional(boolean),
1527
- snapTo: optional(enumeration("grid", "angles", "sides")),
1528
- match: optional(enumeration("similar", "congruent", "approx", "exact")),
1529
- startCoords: optional(array(pairOfNumbers)),
1530
- coord: optional(pairOfNumbers)
1531
- });
1532
- const parsePerseusGraphTypeQuadratic = object({
1533
- type: constant("quadratic"),
1534
- coords: optional(nullable(trio(pairOfNumbers, pairOfNumbers, pairOfNumbers))),
1535
- startCoords: optional(trio(pairOfNumbers, pairOfNumbers, pairOfNumbers)),
1536
- coord: optional(pairOfNumbers)
1537
- });
1538
- const parsePerseusGraphTypeRay = object({
1539
- type: constant("ray"),
1540
- coords: optional(nullable(pair(pairOfNumbers, pairOfNumbers))),
1541
- startCoords: optional(pair(pairOfNumbers, pairOfNumbers)),
1542
- coord: optional(pairOfNumbers)
1543
- });
1544
- const parsePerseusGraphTypeSegment = object({
1545
- type: constant("segment"),
1546
- numSegments: optional(number),
1547
- coords: optional(nullable(array(pair(pairOfNumbers, pairOfNumbers)))),
1548
- startCoords: optional(array(pair(pairOfNumbers, pairOfNumbers))),
1549
- coord: optional(pairOfNumbers)
1550
- });
1551
- const parsePerseusGraphTypeSinusoid = object({
1552
- type: constant("sinusoid"),
1553
- coords: optional(nullable(array(pairOfNumbers))),
1554
- startCoords: optional(array(pairOfNumbers)),
1555
- coord: optional(pairOfNumbers)
1556
- });
1557
- const parsePerseusGraphType = discriminatedUnionOn("type").withBranch("angle", parsePerseusGraphTypeAngle).withBranch("circle", parsePerseusGraphTypeCircle).withBranch("linear", parsePerseusGraphTypeLinear).withBranch("linear-system", parsePerseusGraphTypeLinearSystem).withBranch("none", parsePerseusGraphTypeNone).withBranch("point", parsePerseusGraphTypePoint).withBranch("polygon", parsePerseusGraphTypePolygon).withBranch("quadratic", parsePerseusGraphTypeQuadratic).withBranch("ray", parsePerseusGraphTypeRay).withBranch("segment", parsePerseusGraphTypeSegment).withBranch("sinusoid", parsePerseusGraphTypeSinusoid).parser;
1558
- const parseLockedFigureColor = enumeration(...lockedFigureColorNames);
1559
- const parseLockedFigureFillType = enumeration("none", "white", "translucent", "solid");
1560
- const parseLockedLineStyle = enumeration("solid", "dashed");
1561
- const parseLockedLabelType = object({
1562
- type: constant("label"),
1563
- coord: pairOfNumbers,
1564
- text: string,
1565
- color: parseLockedFigureColor,
1566
- size: enumeration("small", "medium", "large")
1567
- });
1568
- const parseLockedPointType = object({
1569
- type: constant("point"),
1570
- coord: pairOfNumbers,
1571
- color: parseLockedFigureColor,
1572
- filled: boolean,
1573
- labels: optional(array(parseLockedLabelType)),
1574
- ariaLabel: optional(string)
1575
- });
1576
- const parseLockedLineType = object({
1577
- type: constant("line"),
1578
- kind: enumeration("line", "ray", "segment"),
1579
- points: pair(parseLockedPointType, parseLockedPointType),
1580
- color: parseLockedFigureColor,
1581
- lineStyle: parseLockedLineStyle,
1582
- showPoint1: defaulted(boolean, () => false),
1583
- showPoint2: defaulted(boolean, () => false),
1584
- labels: optional(array(parseLockedLabelType)),
1585
- ariaLabel: optional(string)
1586
- });
1587
- const parseLockedVectorType = object({
1588
- type: constant("vector"),
1589
- points: pair(pairOfNumbers, pairOfNumbers),
1590
- color: parseLockedFigureColor,
1591
- labels: optional(array(parseLockedLabelType)),
1592
- ariaLabel: optional(string)
1593
- });
1594
- const parseLockedEllipseType = object({
1595
- type: constant("ellipse"),
1596
- center: pairOfNumbers,
1597
- radius: pairOfNumbers,
1598
- angle: number,
1599
- color: parseLockedFigureColor,
1600
- fillStyle: parseLockedFigureFillType,
1601
- strokeStyle: parseLockedLineStyle,
1602
- labels: optional(array(parseLockedLabelType)),
1603
- ariaLabel: optional(string)
1604
- });
1605
- const parseLockedPolygonType = object({
1606
- type: constant("polygon"),
1607
- points: array(pairOfNumbers),
1608
- color: parseLockedFigureColor,
1609
- showVertices: boolean,
1610
- fillStyle: parseLockedFigureFillType,
1611
- strokeStyle: parseLockedLineStyle,
1612
- labels: optional(array(parseLockedLabelType)),
1613
- ariaLabel: optional(string)
1614
- });
1615
- const parseLockedFunctionDomain = defaulted(pair(defaulted(number, () => -Infinity), defaulted(number, () => Infinity)), () => [-Infinity, Infinity]);
1616
- const parseLockedFunctionType = object({
1617
- type: constant("function"),
1618
- color: parseLockedFigureColor,
1619
- strokeStyle: parseLockedLineStyle,
1620
- equation: string,
1621
- directionalAxis: enumeration("x", "y"),
1622
- domain: parseLockedFunctionDomain,
1623
- labels: optional(array(parseLockedLabelType)),
1624
- ariaLabel: optional(string)
1625
- });
1626
- const parseLockedFigure = discriminatedUnionOn("type").withBranch("point", parseLockedPointType).withBranch("line", parseLockedLineType).withBranch("vector", parseLockedVectorType).withBranch("ellipse", parseLockedEllipseType).withBranch("polygon", parseLockedPolygonType).withBranch("function", parseLockedFunctionType).withBranch("label", parseLockedLabelType).parser;
1627
- const parseInteractiveGraphWidget = parseWidget(constant("interactive-graph"), object({
1628
- step: pairOfNumbers,
1629
- gridStep: optional(pairOfNumbers),
1630
- snapStep: optional(pairOfNumbers),
1631
- backgroundImage: optional(parsePerseusImageBackground),
1632
- markings: enumeration("graph", "grid", "none"),
1633
- labels: optional(array(string)),
1634
- showProtractor: boolean,
1635
- showRuler: optional(boolean),
1636
- showTooltips: optional(boolean),
1637
- rulerLabel: optional(string),
1638
- rulerTicks: optional(number),
1639
- range: pair(pairOfNumbers, pairOfNumbers),
1640
- graph: defaulted(parsePerseusGraphType, () => ({
1641
- type: "linear"
1642
- })),
1643
- correct: parsePerseusGraphType,
1644
- lockedFigures: optional(array(parseLockedFigure)),
1645
- fullGraphLabel: optional(string),
1646
- fullGraphAriaDescription: optional(string)
1647
- }));
1648
-
1649
- const parseLabelImageWidget = parseWidget(constant("label-image"), object({
1650
- choices: array(string),
1651
- imageUrl: string,
1652
- imageAlt: string,
1653
- imageHeight: number,
1654
- imageWidth: number,
1655
- markers: array(object({
1656
- answers: array(string),
1657
- label: string,
1658
- x: number,
1659
- y: number
1660
- })),
1661
- hideChoicesFromInstructions: boolean,
1662
- multipleAnswers: boolean,
1663
- static: defaulted(boolean, () => false)
1664
- }));
1665
-
1666
- const parseMatcherWidget = parseWidget(constant("matcher"), object({
1667
- labels: array(string),
1668
- left: array(string),
1669
- right: array(string),
1670
- orderMatters: boolean,
1671
- padding: boolean
1672
- }));
1673
-
1674
- const numberOrString = union(number).or(string).parser;
1675
- const numeric = pipeParsers(defaulted(numberOrString, () => NaN)).then(stringToNumber).parser;
1676
- const parseMatrixWidget = parseWidget(defaulted(constant("matrix"), () => "matrix"), object({
1677
- prefix: optional(string),
1678
- suffix: optional(string),
1679
- answers: array(array(numeric)),
1680
- cursorPosition: optional(array(number)),
1681
- matrixBoardSize: array(number),
1682
- static: optional(boolean)
1683
- }));
1684
-
1685
- const parseMeasurerWidget = parseWidget(constant("measurer"), object({
1686
- image: defaulted(parsePerseusImageBackground, () => ({
1687
- url: null,
1688
- top: 0,
1689
- left: 0
1690
- })),
1691
- showProtractor: boolean,
1692
- showRuler: boolean,
1693
- rulerLabel: string,
1694
- rulerTicks: number,
1695
- rulerPixels: number,
1696
- rulerLength: number,
1697
- box: pair(number, number),
1698
- static: defaulted(boolean, () => false)
1699
- }));
1700
-
1701
- const parseMoleculeRendererWidget = parseWidget(constant("molecule-renderer"), object({
1702
- widgetId: string,
1703
- rotationAngle: optional(number),
1704
- smiles: optional(string)
1705
- }));
1706
-
1707
- const emptyStringToNull = pipeParsers(constant("")).then(convert(() => null)).parser;
1708
- const parseNumberLineWidget = parseWidget(constant("number-line"), object({
1709
- range: array(number),
1710
- labelRange: array(nullable(union(number).or(emptyStringToNull).parser)),
1711
- labelStyle: string,
1712
- labelTicks: boolean,
1713
- isTickCtrl: optional(nullable(boolean)),
1714
- divisionRange: array(number),
1715
- numDivisions: optional(nullable(number)),
1716
- snapDivisions: defaulted(number, () => 2),
1717
- tickStep: optional(nullable(number)),
1718
- correctRel: optional(nullable(string)),
1719
- correctX: nullable(number),
1720
- initialX: optional(nullable(number)),
1721
- showTooltips: optional(boolean),
1722
- static: defaulted(boolean, () => false)
1723
- }));
1724
-
1725
- const parseMathFormat = enumeration("integer", "mixed", "improper", "proper", "decimal", "percent", "pi");
1726
- const parseSimplify = pipeParsers(union(constant(null)).or(constant(undefined)).or(boolean).or(constant("required")).or(constant("correct")).or(constant("enforced")).or(constant("optional")).or(constant("accepted")).parser).then(convert(deprecatedSimplifyValuesToRequired)).parser;
1727
- function deprecatedSimplifyValuesToRequired(simplify) {
1728
- switch (simplify) {
1729
- case "enforced":
1730
- case "required":
1731
- case "optional":
1732
- return simplify;
1733
- default:
1734
- return "required";
1735
- }
1736
- }
1737
- const parseNumericInputWidget = parseWidget(constant("numeric-input"), object({
1738
- answers: array(object({
1739
- message: string,
1740
- value: optional(nullable(number)),
1741
- status: string,
1742
- answerForms: defaulted(array(parseMathFormat), () => undefined),
1743
- strict: boolean,
1744
- maxError: optional(nullable(number)),
1745
- simplify: parseSimplify
1746
- })),
1747
- labelText: optional(string),
1748
- size: string,
1749
- coefficient: defaulted(boolean, () => false),
1750
- rightAlign: optional(boolean),
1751
- static: defaulted(boolean, () => false),
1752
- answerForms: optional(array(object({
1753
- name: parseMathFormat,
1754
- simplify: parseSimplify
1755
- })))
1756
- }));
1757
-
1758
- function parseRenderer(rawValue, ctx) {
1759
- return parsePerseusRenderer(rawValue, ctx);
1760
- }
1761
- const largeToAuto = (height, ctx) => {
1762
- if (height === "large") {
1763
- return ctx.success("auto");
1764
- }
1765
- return ctx.success(height);
1766
- };
1767
- const parseOrdererWidget = parseWidget(constant("orderer"), object({
1768
- options: defaulted(array(parseRenderer), () => []),
1769
- correctOptions: array(parseRenderer),
1770
- otherOptions: array(parseRenderer),
1771
- height: pipeParsers(enumeration("normal", "auto", "large")).then(largeToAuto).parser,
1772
- layout: defaulted(enumeration("horizontal", "vertical"), () => "horizontal")
1773
- }));
1774
-
1775
- const parsePassageRefWidget = parseWidget(constant("passage-ref"), object({
1776
- passageNumber: number,
1777
- referenceNumber: number,
1778
- summaryText: optional(string)
1779
- }));
1780
-
1781
- const parsePassageWidget = parseWidget(constant("passage"), object({
1782
- footnotes: defaulted(string, () => ""),
1783
- passageText: string,
1784
- passageTitle: defaulted(string, () => ""),
1785
- showLineNumbers: boolean,
1786
- static: defaulted(boolean, () => false)
1787
- }));
1788
-
1789
- const parsePhetSimulationWidget = parseWidget(constant("phet-simulation"), object({
1790
- url: string,
1791
- description: string
1792
- }));
1793
-
1794
- const parsePlotterWidget = parseWidget(constant("plotter"), object({
1795
- labels: array(string),
1796
- categories: array(string),
1797
- type: enumeration(...plotterPlotTypes),
1798
- maxY: number,
1799
- scaleY: defaulted(number, () => 1),
1800
- labelInterval: optional(nullable(number)),
1801
- snapsPerLine: defaulted(number, () => 2),
1802
- starting: array(number),
1803
- correct: array(number),
1804
- picUrl: optional(nullable(string)),
1805
- picSize: optional(nullable(number)),
1806
- picBoxHeight: optional(nullable(number)),
1807
- plotDimensions: defaulted(array(number), () => [380, 300])
1808
- }));
1809
-
1810
- const parsePythonProgramWidget = parseWidget(constant("python-program"), object({
1811
- programID: string,
1812
- height: number
1813
- }));
1814
-
1815
- const _excluded$a = ["noneOfTheAbove"];
1816
- const currentVersion$3 = {
1817
- major: 2,
1818
- minor: 0
1819
- };
1820
- function deriveNumCorrect(options) {
1821
- const {
1822
- choices,
1823
- numCorrect
1824
- } = options;
1825
- return numCorrect != null ? numCorrect : choices.filter(c => c.correct).length;
1826
- }
1827
- const widgetOptionsUpgrades$2 = {
1828
- "2": v1props => {
1829
- const upgraded = _extends({}, v1props, {
1830
- numCorrect: deriveNumCorrect(v1props)
1831
- });
1832
- return upgraded;
1833
- },
1834
- "1": v0props => {
1835
- const {
1836
- noneOfTheAbove
1837
- } = v0props,
1838
- rest = _objectWithoutPropertiesLoose(v0props, _excluded$a);
1839
- if (noneOfTheAbove) {
1840
- throw new Error("radio widget v0 no longer supports auto noneOfTheAbove");
1841
- }
1842
- return _extends({}, rest, {
1843
- hasNoneOfTheAbove: false
1844
- });
1845
- }
1846
- };
1847
- const defaultWidgetOptions$v = {
1848
- choices: [{}, {}, {}, {}],
1849
- displayCount: null,
1850
- randomize: false,
1851
- hasNoneOfTheAbove: false,
1852
- multipleSelect: false,
1853
- countChoices: false,
1854
- deselectEnabled: false
1855
- };
1856
-
1857
- const _excluded$9 = ["noneOfTheAbove"];
1858
- const version2 = optional(object({
1859
- major: constant(2),
1860
- minor: number
1861
- }));
1862
- const parseRadioWidgetV2 = parseWidgetWithVersion(version2, constant("radio"), object({
1863
- numCorrect: optional(number),
1864
- choices: array(object({
1865
- content: defaulted(string, () => ""),
1866
- clue: optional(string),
1867
- correct: optional(boolean),
1868
- isNoneOfTheAbove: optional(boolean),
1869
- widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
1870
- })),
1871
- hasNoneOfTheAbove: optional(boolean),
1872
- countChoices: optional(boolean),
1873
- randomize: optional(boolean),
1874
- multipleSelect: optional(boolean),
1875
- deselectEnabled: optional(boolean),
1876
- onePerLine: optional(boolean),
1877
- displayCount: optional(any),
1878
- noneOfTheAbove: optional(constant(false))
1879
- }));
1880
- const version1 = optional(object({
1881
- major: constant(1),
1882
- minor: number
1883
- }));
1884
- const parseRadioWidgetV1 = parseWidgetWithVersion(version1, constant("radio"), object({
1885
- choices: array(object({
1886
- content: defaulted(string, () => ""),
1887
- clue: optional(string),
1888
- correct: optional(boolean),
1889
- isNoneOfTheAbove: optional(boolean),
1890
- widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => undefined)
1891
- })),
1892
- hasNoneOfTheAbove: optional(boolean),
1893
- countChoices: optional(boolean),
1894
- randomize: optional(boolean),
1895
- multipleSelect: optional(boolean),
1896
- deselectEnabled: optional(boolean),
1897
- onePerLine: optional(boolean),
1898
- displayCount: optional(any),
1899
- noneOfTheAbove: optional(constant(false))
1900
- }));
1901
- function migrateV1ToV2(widget) {
1902
- const {
1903
- options
1904
- } = widget;
1905
- return _extends({}, widget, {
1906
- version: {
1907
- major: 2,
1908
- minor: 0
1909
- },
1910
- options: _extends({}, options, {
1911
- numCorrect: deriveNumCorrect(options)
1912
- })
1913
- });
1914
- }
1915
- const version0 = optional(object({
1916
- major: constant(0),
1917
- minor: number
1918
- }));
1919
- const parseRadioWidgetV0 = parseWidgetWithVersion(version0, constant("radio"), object({
1920
- choices: array(object({
1921
- content: defaulted(string, () => ""),
1922
- clue: optional(string),
1923
- correct: optional(boolean),
1924
- isNoneOfTheAbove: optional(boolean),
1925
- widgets: optional((rawVal, ctx) => parseWidgetsMap(rawVal, ctx))
1926
- })),
1927
- hasNoneOfTheAbove: optional(boolean),
1928
- countChoices: optional(boolean),
1929
- randomize: optional(boolean),
1930
- multipleSelect: optional(boolean),
1931
- deselectEnabled: optional(boolean),
1932
- onePerLine: optional(boolean),
1933
- displayCount: optional(any),
1934
- noneOfTheAbove: optional(constant(false))
1935
- }));
1936
- function migrateV0ToV1(widget) {
1937
- const {
1938
- options
1939
- } = widget;
1940
- const rest = _objectWithoutPropertiesLoose(options, _excluded$9);
1941
- return _extends({}, widget, {
1942
- version: {
1943
- major: 1,
1944
- minor: 0
1945
- },
1946
- options: _extends({}, rest, {
1947
- hasNoneOfTheAbove: false
1948
- })
1949
- });
1950
- }
1951
- const parseRadioWidget = versionedWidgetOptions(2, parseRadioWidgetV2).withMigrationFrom(1, parseRadioWidgetV1, migrateV1ToV2).withMigrationFrom(0, parseRadioWidgetV0, migrateV0ToV1).parser;
1952
-
1953
- const parseSorterWidget = parseWidget(constant("sorter"), object({
1954
- correct: array(string),
1955
- padding: boolean,
1956
- layout: enumeration("horizontal", "vertical")
1957
- }));
1958
-
1959
- const parseTableWidget = parseWidget(constant("table"), object({
1960
- headers: array(string),
1961
- rows: number,
1962
- columns: number,
1963
- answers: array(array(string))
1964
- }));
1965
-
1966
- const parseVideoWidget = parseWidget(constant("video"), object({
1967
- location: string,
1968
- static: optional(boolean)
1969
- }));
1970
-
1971
- const parseWidgetsMap = (rawValue, ctx) => {
1972
- if (!isObject(rawValue)) {
1973
- return ctx.failure("PerseusWidgetsMap", rawValue);
1974
- }
1975
- const widgetsMap = {};
1976
- for (const key of Object.keys(rawValue)) {
1977
- const entryResult = parseWidgetsMapEntry([key, rawValue[key]], widgetsMap, ctx.forSubtree(key));
1978
- if (isFailure(entryResult)) {
1979
- return entryResult;
1980
- }
1981
- }
1982
- return ctx.success(widgetsMap);
1983
- };
1984
- const parseWidgetsMapEntry = ([id, widget], widgetMap, ctx) => {
1985
- const idComponentsResult = parseWidgetIdComponents(id.split(" "), ctx.forSubtree("(widget ID)"));
1986
- if (isFailure(idComponentsResult)) {
1987
- return idComponentsResult;
1988
- }
1989
- const [type, n] = idComponentsResult.value;
1990
- function parseAndAssign(key, parse) {
1991
- const widgetResult = parse(widget, ctx);
1992
- if (isFailure(widgetResult)) {
1993
- return widgetResult;
1994
- }
1995
- widgetMap[key] = widgetResult.value;
1996
- return ctx.success(undefined);
1997
- }
1998
- switch (type) {
1999
- case "categorizer":
2000
- return parseAndAssign(`categorizer ${n}`, parseCategorizerWidget);
2001
- case "cs-program":
2002
- return parseAndAssign(`cs-program ${n}`, parseCSProgramWidget);
2003
- case "definition":
2004
- return parseAndAssign(`definition ${n}`, parseDefinitionWidget);
2005
- case "dropdown":
2006
- return parseAndAssign(`dropdown ${n}`, parseDropdownWidget);
2007
- case "explanation":
2008
- return parseAndAssign(`explanation ${n}`, parseExplanationWidget);
2009
- case "expression":
2010
- return parseAndAssign(`expression ${n}`, parseExpressionWidget);
2011
- case "grapher":
2012
- return parseAndAssign(`grapher ${n}`, parseGrapherWidget);
2013
- case "group":
2014
- return parseAndAssign(`group ${n}`, parseGroupWidget);
2015
- case "graded-group":
2016
- return parseAndAssign(`graded-group ${n}`, parseGradedGroupWidget);
2017
- case "graded-group-set":
2018
- return parseAndAssign(`graded-group-set ${n}`, parseGradedGroupSetWidget);
2019
- case "iframe":
2020
- return parseAndAssign(`iframe ${n}`, parseIframeWidget);
2021
- case "image":
2022
- return parseAndAssign(`image ${n}`, parseImageWidget);
2023
- case "input-number":
2024
- return parseAndAssign(`input-number ${n}`, parseInputNumberWidget);
2025
- case "interaction":
2026
- return parseAndAssign(`interaction ${n}`, parseInteractionWidget);
2027
- case "interactive-graph":
2028
- return parseAndAssign(`interactive-graph ${n}`, parseInteractiveGraphWidget);
2029
- case "label-image":
2030
- return parseAndAssign(`label-image ${n}`, parseLabelImageWidget);
2031
- case "matcher":
2032
- return parseAndAssign(`matcher ${n}`, parseMatcherWidget);
2033
- case "matrix":
2034
- return parseAndAssign(`matrix ${n}`, parseMatrixWidget);
2035
- case "measurer":
2036
- return parseAndAssign(`measurer ${n}`, parseMeasurerWidget);
2037
- case "molecule-renderer":
2038
- return parseAndAssign(`molecule-renderer ${n}`, parseMoleculeRendererWidget);
2039
- case "number-line":
2040
- return parseAndAssign(`number-line ${n}`, parseNumberLineWidget);
2041
- case "numeric-input":
2042
- return parseAndAssign(`numeric-input ${n}`, parseNumericInputWidget);
2043
- case "orderer":
2044
- return parseAndAssign(`orderer ${n}`, parseOrdererWidget);
2045
- case "passage":
2046
- return parseAndAssign(`passage ${n}`, parsePassageWidget);
2047
- case "passage-ref":
2048
- return parseAndAssign(`passage-ref ${n}`, parsePassageRefWidget);
2049
- case "passage-ref-target":
2050
- return parseAndAssign(`passage-ref-target ${n}`, any);
2051
- case "phet-simulation":
2052
- return parseAndAssign(`phet-simulation ${n}`, parsePhetSimulationWidget);
2053
- case "plotter":
2054
- return parseAndAssign(`plotter ${n}`, parsePlotterWidget);
2055
- case "python-program":
2056
- return parseAndAssign(`python-program ${n}`, parsePythonProgramWidget);
2057
- case "radio":
2058
- return parseAndAssign(`radio ${n}`, parseRadioWidget);
2059
- case "sorter":
2060
- return parseAndAssign(`sorter ${n}`, parseSorterWidget);
2061
- case "table":
2062
- return parseAndAssign(`table ${n}`, parseTableWidget);
2063
- case "video":
2064
- return parseAndAssign(`video ${n}`, parseVideoWidget);
2065
- case "sequence":
2066
- return parseAndAssign(`sequence ${n}`, parseDeprecatedWidget);
2067
- case "lights-puzzle":
2068
- return parseAndAssign(`lights-puzzle ${n}`, parseDeprecatedWidget);
2069
- case "simulator":
2070
- return parseAndAssign(`simulator ${n}`, parseDeprecatedWidget);
2071
- case "transformer":
2072
- return parseAndAssign(`transformer ${n}`, parseDeprecatedWidget);
2073
- default:
2074
- return parseAndAssign(`${type} ${n}`, parseWidget(constant(type), any));
2075
- }
2076
- };
2077
- const parseDeprecatedWidget = parseWidget((_, ctx) => ctx.success("deprecated-standin"), object({}));
2078
- const parseStringToNonNegativeInt = (rawValue, ctx) => {
2079
- if (typeof rawValue !== "string" || !/^(0|[1-9][0-9]*)$/.test(rawValue)) {
2080
- return ctx.failure("a string representing a non-negative integer", rawValue);
2081
- }
2082
- return ctx.success(+rawValue);
2083
- };
2084
- const parseWidgetIdComponents = pair(string, parseStringToNonNegativeInt);
2085
-
2086
- const parsePerseusRenderer = defaulted(object({
2087
- content: defaulted(string, () => ""),
2088
- widgets: defaulted((rawVal, ctx) => parseWidgetsMap(rawVal, ctx), () => ({})),
2089
- images: parseImages,
2090
- metadata: any
2091
- }), () => ({
2092
- content: "",
2093
- widgets: {},
2094
- images: {}
2095
- }));
2096
-
2097
- const parsePerseusArticle = union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
2098
-
2099
- const parseHint = object({
2100
- replace: defaulted(boolean, () => undefined),
2101
- content: string,
2102
- widgets: defaulted(parseWidgetsMap, () => ({})),
2103
- images: parseImages,
2104
- metadata: any
2105
- });
111
+ const KeypadKeys=["PLUS","MINUS","NEGATIVE","TIMES","DIVIDE","DECIMAL","PERIOD","PERCENT","CDOT","EQUAL","NEQ","GT","LT","GEQ","LEQ","FRAC_INCLUSIVE","FRAC_EXCLUSIVE","FRAC","EXP","EXP_2","EXP_3","SQRT","CUBE_ROOT","RADICAL","LEFT_PAREN","RIGHT_PAREN","LN","LOG","LOG_N","SIN","COS","TAN","PI","THETA","UP","RIGHT","DOWN","LEFT","BACKSPACE","DISMISS","JUMP_OUT_PARENTHESES","JUMP_OUT_EXPONENT","JUMP_OUT_BASE","JUMP_INTO_NUMERATOR","JUMP_OUT_NUMERATOR","JUMP_OUT_DENOMINATOR","NUM_0","NUM_1","NUM_2","NUM_3","NUM_4","NUM_5","NUM_6","NUM_7","NUM_8","NUM_9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
2106
112
 
2107
- const parsePerseusAnswerArea = pipeParsers(defaulted(object({}), () => ({}))).then(convert(toAnswerArea)).parser;
2108
- function toAnswerArea(raw) {
2109
- return {
2110
- zTable: !!raw.zTable,
2111
- calculator: !!raw.calculator,
2112
- chi2Table: !!raw.chi2Table,
2113
- financialCalculatorMonthlyPayment: !!raw.financialCalculatorMonthlyPayment,
2114
- financialCalculatorTotalAmount: !!raw.financialCalculatorTotalAmount,
2115
- financialCalculatorTimeToPayOff: !!raw.financialCalculatorTimeToPayOff,
2116
- periodicTable: !!raw.periodicTable,
2117
- periodicTableWithKey: !!raw.periodicTableWithKey,
2118
- tTable: !!raw.tTable
2119
- };
2120
- }
113
+ function deriveExtraKeys(widgetOptions){if(widgetOptions.extraKeys){return widgetOptions.extraKeys}const defaultKeys=["PI"];if(widgetOptions.answerForms==null){return defaultKeys}const uniqueExtraVariables={};const uniqueExtraConstants={};for(const answerForm of widgetOptions.answerForms){const maybeExpr=KAS__namespace.parse(answerForm.value,widgetOptions);if(maybeExpr.parsed){const expr=maybeExpr.expr;const isGreek=symbol=>symbol==="pi"||symbol==="theta";const toKey=symbol=>isGreek(symbol)?symbol.toUpperCase():symbol;const isKey=key=>KeypadKeys.includes(key);for(const variable of expr.getVars()){const maybeKey=toKey(variable);if(isKey(maybeKey)){uniqueExtraVariables[maybeKey]=true;}}for(const constant of expr.getConsts()){const maybeKey=toKey(constant);if(isKey(maybeKey)){uniqueExtraConstants[maybeKey]=true;}}}}const extraVariables=Object.keys(uniqueExtraVariables).sort();const extraConstants=Object.keys(uniqueExtraConstants).sort();const extraKeys=[...extraVariables,...extraConstants];if(!extraKeys.length){return defaultKeys}return extraKeys}
2121
114
 
2122
- const parsePerseusItem$1 = object({
2123
- question: parsePerseusRenderer,
2124
- hints: defaulted(array(parseHint), () => []),
2125
- answerArea: parsePerseusAnswerArea,
2126
- itemDataVersion: optional(nullable(object({
2127
- major: number,
2128
- minor: number
2129
- }))),
2130
- answer: any
2131
- });
115
+ function convert(f){return (rawValue,ctx)=>ctx.success(f(rawValue))}
2132
116
 
2133
- function parsePerseusItem(json) {
2134
- if (isRealJSONParse(JSON.parse)) {
2135
- return JSON.parse(json);
2136
- }
2137
- throw new Error("Something went wrong.");
2138
- }
2139
- function parseAndMigratePerseusItem(json) {
2140
- throwErrorIfCheatingDetected();
2141
- const object = JSON.parse(json);
2142
- const result = parse(object, parsePerseusItem$1);
2143
- if (isFailure(result)) {
2144
- return failure({
2145
- message: result.detail,
2146
- invalidObject: object
2147
- });
2148
- }
2149
- return result;
2150
- }
2151
- function parseAndMigratePerseusArticle(json) {
2152
- throwErrorIfCheatingDetected();
2153
- const object = JSON.parse(json);
2154
- const result = parse(object, parsePerseusArticle);
2155
- if (isFailure(result)) {
2156
- return failure({
2157
- message: result.detail,
2158
- invalidObject: object
2159
- });
2160
- }
2161
- return result;
2162
- }
2163
- function throwErrorIfCheatingDetected() {
2164
- if (!isRealJSONParse(JSON.parse)) {
2165
- throw new Error("Something went wrong.");
2166
- }
2167
- }
117
+ const parseLegacyButtonSet=enumeration("basic","basic+div","trig","prealgebra","logarithms","basic relations","advanced relations","scientific");const parseLegacyButtonSets=defaulted(array(parseLegacyButtonSet),()=>["basic","trig","prealgebra","logarithms"]);
2168
118
 
2169
- const libName = "@khanacademy/perseus-core";
2170
- const libVersion = "6.0.0";
2171
- addLibraryVersionToPerseusDebug(libName, libVersion);
2172
-
2173
- const Errors = Object.freeze({
2174
- Unknown: "Unknown",
2175
- Internal: "Internal",
2176
- InvalidInput: "InvalidInput",
2177
- NotAllowed: "NotAllowed",
2178
- TransientService: "TransientService",
2179
- Service: "Service"
2180
- });
119
+ function versionedWidgetOptions(latestMajorVersion,parseLatest){return new VersionedWidgetOptionsParserBuilder(latestMajorVersion,parseLatest,latest=>latest,(raw,ctx)=>ctx.failure("widget options with a known version number",raw))}class VersionedWidgetOptionsParserBuilder{withMigrationFrom(majorVersion,parseOldVersion,migrateToNextVersion){const parseOtherVersions=this.parser;const migrateToLatest=old=>this.migrateToLatest(migrateToNextVersion(old));return new VersionedWidgetOptionsParserBuilder(majorVersion,parseOldVersion,migrateToLatest,parseOtherVersions)}constructor(majorVersion,parseThisVersion,migrateToLatest,parseOtherVersions){this.migrateToLatest=migrateToLatest;this.parseOtherVersions=parseOtherVersions;const parseThisVersionAndMigrateToLatest=pipeParsers(parseThisVersion).then(convert(this.migrateToLatest)).parser;this.parser=(raw,ctx)=>{if(!isObject(raw)){return ctx.failure("object",raw)}const versionParseResult=parseVersionedObject(raw,ctx);if(isFailure(versionParseResult)){return versionParseResult}if(versionParseResult.value.version.major!==majorVersion){return this.parseOtherVersions(raw,ctx)}return parseThisVersionAndMigrateToLatest(raw,ctx)};}}const parseVersionedObject=object({version:defaulted(object({major:number,minor:number}),()=>({major:0,minor:0}))});
2181
120
 
2182
- class PerseusError extends Error {
2183
- constructor(message, kind, options) {
2184
- super(message);
2185
- this.kind = void 0;
2186
- this.metadata = void 0;
2187
- this.kind = kind;
2188
- this.metadata = options == null ? void 0 : options.metadata;
2189
- }
2190
- }
121
+ const stringOrNumberOrNullOrUndefined=union(string).or(number).or(constant(null)).or(constant(undefined)).parser;const parsePossiblyInvalidAnswerForm=object({value:optional(string),form:defaulted(boolean,()=>false),simplify:defaulted(boolean,()=>false),considered:enumeration("correct","wrong","ungraded"),key:pipeParsers(stringOrNumberOrNullOrUndefined).then(convert(String)).parser});function removeInvalidAnswerForms(possiblyInvalid){const valid=[];for(const answerForm of possiblyInvalid){const{value}=answerForm;if(value!=null){valid.push({...answerForm,value});}}return valid}const version2$1=object({major:constant(2),minor:number});const parseExpressionWidgetV2=parseWidgetWithVersion(version2$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused")),extraKeys:array(enumeration(...KeypadKeys))}));const version1$1=object({major:constant(1),minor:number});const parseExpressionWidgetV1=parseWidgetWithVersion(version1$1,constant("expression"),object({answerForms:pipeParsers(array(parsePossiblyInvalidAnswerForm)).then(convert(removeInvalidAnswerForms)).parser,functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV1ToV2$1(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:options.answerForms,extraKeys:deriveExtraKeys(options)}}}const version0$1=optional(object({major:constant(0),minor:number}));const parseExpressionWidgetV0=parseWidgetWithVersion(version0$1,constant("expression"),object({functions:array(string),times:boolean,visibleLabel:optional(string),ariaLabel:optional(string),form:boolean,simplify:boolean,value:string,buttonSets:parseLegacyButtonSets,buttonsVisible:optional(enumeration("always","never","focused"))}));function migrateV0ToV1$1(widget){const{options}=widget;return {...widget,version:{major:1,minor:0},options:{times:options.times,buttonSets:options.buttonSets,functions:options.functions,buttonsVisible:options.buttonsVisible,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,answerForms:[{considered:"correct",form:options.form,simplify:options.simplify,value:options.value}]}}}const parseExpressionWidget=versionedWidgetOptions(2,parseExpressionWidgetV2).withMigrationFrom(1,parseExpressionWidgetV1,migrateV1ToV2$1).withMigrationFrom(0,parseExpressionWidgetV0,migrateV0ToV1$1).parser;
2191
122
 
2192
- const pluck = function pluck(table, subKey) {
2193
- return _.object(_.map(table, function (value, key) {
2194
- return [key, value[subKey]];
2195
- }));
2196
- };
2197
- const mapObject = function mapObject(obj, lambda) {
2198
- const result = {};
2199
- Object.keys(obj).forEach(key => {
2200
- result[key] = lambda(obj[key], key);
2201
- });
2202
- return result;
2203
- };
2204
-
2205
- function getCategorizerPublicWidgetOptions(options) {
2206
- return {
2207
- items: options.items,
2208
- categories: options.categories,
2209
- randomizeItems: options.randomizeItems,
2210
- static: options.static
2211
- };
2212
- }
123
+ const falseToNull=pipeParsers(constant(false)).then(convert(()=>null)).parser;const parseGradedGroupWidgetOptions=object({title:defaulted(string,()=>""),hasHint:optional(nullable(boolean)),hint:union(falseToNull).or(constant(null)).or(constant(undefined)).or((rawVal,ctx)=>parsePerseusRenderer(rawVal,ctx)).parser,content:string,widgets:(rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),widgetEnabled:optional(nullable(boolean)),immutableWidgets:optional(nullable(boolean)),images:record(string,object({width:number,height:number}))});const parseGradedGroupWidget=parseWidget(constant("graded-group"),parseGradedGroupWidgetOptions);
2213
124
 
2214
- const defaultWidgetOptions$u = {
2215
- items: [],
2216
- categories: [],
2217
- values: [],
2218
- randomizeItems: false
2219
- };
2220
- const categorizerWidgetLogic = {
2221
- name: "categorizer",
2222
- defaultWidgetOptions: defaultWidgetOptions$u,
2223
- getPublicWidgetOptions: getCategorizerPublicWidgetOptions
2224
- };
2225
-
2226
- function getCSProgramPublicWidgetOptions(options) {
2227
- return options;
2228
- }
125
+ const parseGradedGroupSetWidget=parseWidget(constant("graded-group-set"),object({gradedGroups:array(parseGradedGroupWidgetOptions)}));
2229
126
 
2230
- const DEFAULT_HEIGHT = 400;
2231
- const defaultWidgetOptions$t = {
2232
- programID: "",
2233
- programType: null,
2234
- settings: [{
2235
- name: "",
2236
- value: ""
2237
- }],
2238
- showEditor: false,
2239
- showButtons: false,
2240
- height: DEFAULT_HEIGHT
2241
- };
2242
- const csProgramWidgetLogic = {
2243
- name: "cs-program",
2244
- defaultWidgetOptions: defaultWidgetOptions$t,
2245
- supportedAlignments: ["block", "full-width"],
2246
- getPublicWidgetOptions: getCSProgramPublicWidgetOptions
2247
- };
2248
-
2249
- const defaultWidgetOptions$s = {
2250
- togglePrompt: "",
2251
- definition: ""
2252
- };
2253
- const definitionWidgetLogic = {
2254
- name: "definition",
2255
- defaultWidgetOptions: defaultWidgetOptions$s,
2256
- defaultAlignment: "inline"
2257
- };
2258
-
2259
- function getDropdownPublicWidgetOptions(options) {
2260
- return {
2261
- choices: options.choices.map(choice => ({
2262
- content: choice.content
2263
- })),
2264
- placeholder: options.placeholder,
2265
- static: options.static,
2266
- visibleLabel: options.visibleLabel,
2267
- ariaLabel: options.ariaLabel
2268
- };
2269
- }
127
+ function discriminatedUnionOn(discriminantKey){const noMoreBranches=(raw,ctx)=>{if(!isObject(raw)){return ctx.failure("object",raw)}return ctx.forSubtree(discriminantKey).failure("a valid value",raw[discriminantKey])};return new DiscriminatedUnionBuilder(discriminantKey,noMoreBranches)}class DiscriminatedUnionBuilder{withBranch(discriminantValue,parseNewVariant){const parseNewBranch=discriminatedUnionBranch(this.discriminantKey,discriminantValue,parseNewVariant,this.parser);return new DiscriminatedUnionBuilder(this.discriminantKey,parseNewBranch)}constructor(discriminantKey,parser){this.discriminantKey=discriminantKey;this.parser=parser;}}function discriminatedUnionBranch(discriminantKey,discriminantValue,parseVariant,parseOtherBranches){return (raw,ctx)=>{if(!isObject(raw)){return ctx.failure("object",raw)}if(raw[discriminantKey]===discriminantValue){return parseVariant(raw,ctx)}return parseOtherBranches(raw,ctx)}}
2270
128
 
2271
- const defaultWidgetOptions$r = {
2272
- placeholder: "",
2273
- choices: [{
2274
- content: "",
2275
- correct: false
2276
- }]
2277
- };
2278
- const dropdownWidgetLogic = {
2279
- name: "definition",
2280
- defaultWidgetOptions: defaultWidgetOptions$r,
2281
- defaultAlignment: "inline-block",
2282
- getPublicWidgetOptions: getDropdownPublicWidgetOptions
2283
- };
2284
-
2285
- const defaultWidgetOptions$q = {
2286
- showPrompt: "Explain",
2287
- hidePrompt: "Hide explanation",
2288
- explanation: "explanation goes here\n\nmore explanation",
2289
- widgets: {}
2290
- };
2291
- const explanationWidgetLogic = {
2292
- name: "explanation",
2293
- defaultWidgetOptions: defaultWidgetOptions$q,
2294
- defaultAlignment: "inline"
2295
- };
2296
-
2297
- const currentVersion$2 = {
2298
- major: 2,
2299
- minor: 0
2300
- };
2301
- const widgetOptionsUpgrades$1 = {
2302
- "2": v1options => {
2303
- return {
2304
- times: v1options.times,
2305
- buttonSets: v1options.buttonSets,
2306
- functions: v1options.functions,
2307
- buttonsVisible: v1options.buttonsVisible,
2308
- visibleLabel: v1options.visibleLabel,
2309
- ariaLabel: v1options.ariaLabel,
2310
- answerForms: v1options.answerForms,
2311
- extraKeys: v1options.extraKeys || deriveExtraKeys(v1options)
2312
- };
2313
- },
2314
- "1": v0options => {
2315
- return {
2316
- times: v0options.times,
2317
- buttonSets: v0options.buttonSets,
2318
- functions: v0options.functions,
2319
- buttonsVisible: v0options.buttonsVisible,
2320
- visibleLabel: v0options.visibleLabel,
2321
- ariaLabel: v0options.ariaLabel,
2322
- extraKeys: v0options.extraKeys,
2323
- answerForms: [{
2324
- considered: "correct",
2325
- form: v0options.form,
2326
- simplify: v0options.simplify,
2327
- value: v0options.value
2328
- }]
2329
- };
2330
- }
2331
- };
2332
- const defaultWidgetOptions$p = {
2333
- answerForms: [],
2334
- times: false,
2335
- buttonSets: ["basic"],
2336
- functions: ["f", "g", "h"]
2337
- };
2338
-
2339
- function getExpressionPublicWidgetOptions(options) {
2340
- return {
2341
- buttonSets: options.buttonSets,
2342
- functions: options.functions,
2343
- times: options.times,
2344
- visibleLabel: options.visibleLabel,
2345
- ariaLabel: options.ariaLabel,
2346
- buttonsVisible: options.buttonsVisible,
2347
- extraKeys: options.extraKeys
2348
- };
2349
- }
129
+ const pairOfNumbers$3=pair(number,number);const pairOfPoints=pair(pairOfNumbers$3,pairOfNumbers$3);const parseGrapherWidget=parseWidget(constant("grapher"),object({availableTypes:array(enumeration("absolute_value","exponential","linear","logarithm","quadratic","sinusoid","tangent")),correct:discriminatedUnionOn("type").withBranch("absolute_value",object({type:constant("absolute_value"),coords:nullable(pairOfPoints)})).withBranch("exponential",object({type:constant("exponential"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("linear",object({type:constant("linear"),coords:nullable(pairOfPoints)})).withBranch("logarithm",object({type:constant("logarithm"),asymptote:pairOfPoints,coords:nullable(pairOfPoints)})).withBranch("quadratic",object({type:constant("quadratic"),coords:nullable(pairOfPoints)})).withBranch("sinusoid",object({type:constant("sinusoid"),coords:nullable(pairOfPoints)})).withBranch("tangent",object({type:constant("tangent"),coords:nullable(pairOfPoints)})).parser,graph:object({backgroundImage:object({bottom:optional(number),height:optional(number),left:optional(number),scale:optional(number),url:optional(nullable(string)),width:optional(number)}),box:optional(pairOfNumbers$3),editableSettings:optional(array(enumeration("graph","snap","image","measure"))),gridStep:optional(pairOfNumbers$3),labels:pair(string,string),markings:enumeration("graph","none","grid"),range:pair(pairOfNumbers$3,pairOfNumbers$3),rulerLabel:constant(""),rulerTicks:number,showProtractor:optional(boolean),showRuler:optional(boolean),showTooltips:optional(boolean),snapStep:optional(pairOfNumbers$3),step:pairOfNumbers$3,valid:optional(union(boolean).or(string).parser)})}));
2350
130
 
2351
- const expressionWidgetLogic = {
2352
- name: "expression",
2353
- version: currentVersion$2,
2354
- widgetOptionsUpgrades: widgetOptionsUpgrades$1,
2355
- defaultWidgetOptions: defaultWidgetOptions$p,
2356
- defaultAlignment: "inline-block",
2357
- getPublicWidgetOptions: getExpressionPublicWidgetOptions
2358
- };
2359
-
2360
- const defaultWidgetOptions$o = {
2361
- title: "",
2362
- content: "",
2363
- widgets: {},
2364
- images: {},
2365
- hint: null
2366
- };
2367
- const gradedGroupWidgetLogic = {
2368
- name: "graded-group",
2369
- defaultWidgetOptions: defaultWidgetOptions$o
2370
- };
2371
-
2372
- const defaultWidgetOptions$n = {
2373
- gradedGroups: []
2374
- };
2375
- const gradedGroupSetWidgetLogic = {
2376
- name: "graded-group-set",
2377
- defaultWidgetOptions: defaultWidgetOptions$n
2378
- };
2379
-
2380
- const _excluded$8 = ["correct"];
2381
- function getGrapherPublicWidgetOptions(options) {
2382
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$8);
2383
- return publicOptions;
2384
- }
131
+ const parseGroupWidget=parseWidget(constant("group"),(rawVal,ctx)=>parsePerseusRenderer(rawVal,ctx));
2385
132
 
2386
- const defaultWidgetOptions$m = {
2387
- graph: {
2388
- labels: ["x", "y"],
2389
- range: [[-10, 10], [-10, 10]],
2390
- step: [1, 1],
2391
- backgroundImage: {
2392
- url: null
2393
- },
2394
- markings: "graph",
2395
- rulerLabel: "",
2396
- rulerTicks: 10,
2397
- valid: true,
2398
- showTooltips: false
2399
- },
2400
- correct: {
2401
- type: "linear",
2402
- coords: null
2403
- },
2404
- availableTypes: ["linear"]
2405
- };
2406
- const grapherWidgetLogic = {
2407
- name: "grapher",
2408
- defaultWidgetOptions: defaultWidgetOptions$m,
2409
- getPublicWidgetOptions: getGrapherPublicWidgetOptions
2410
- };
2411
-
2412
- const defaultWidgetOptions$l = {
2413
- content: "",
2414
- widgets: {},
2415
- images: {}
2416
- };
2417
- const groupWidgetLogic = {
2418
- name: "group",
2419
- defaultWidgetOptions: defaultWidgetOptions$l
2420
- };
2421
-
2422
- function getIFramePublicWidgetOptions(options) {
2423
- return options;
2424
- }
133
+ const parseIframeWidget=parseWidget(constant("iframe"),object({url:string,settings:optional(array(object({name:string,value:string}))),width:union(number).or(string).parser,height:union(number).or(string).parser,allowFullScreen:defaulted(boolean,()=>false),allowTopNavigation:optional(boolean),static:defaulted(boolean,()=>false)}));
2425
134
 
2426
- const defaultWidgetOptions$k = {
2427
- url: "",
2428
- settings: [{
2429
- name: "",
2430
- value: ""
2431
- }],
2432
- width: "400",
2433
- height: "400",
2434
- allowFullScreen: false,
2435
- allowTopNavigation: false
2436
- };
2437
- const iframeWidgetLogic = {
2438
- name: "iframe",
2439
- defaultWidgetOptions: defaultWidgetOptions$k,
2440
- getPublicWidgetOptions: getIFramePublicWidgetOptions
2441
- };
2442
-
2443
- const defaultWidgetOptions$j = {
2444
- title: "",
2445
- range: [[0, 10], [0, 10]],
2446
- box: [400, 400],
2447
- backgroundImage: {
2448
- url: null,
2449
- width: 0,
2450
- height: 0
2451
- },
2452
- labels: [],
2453
- alt: "",
2454
- caption: ""
2455
- };
2456
- const imageWidgetLogic = {
2457
- name: "image",
2458
- defaultWidgetOptions: defaultWidgetOptions$j,
2459
- supportedAlignments: ["block", "full-width"],
2460
- defaultAlignment: "block"
2461
- };
2462
-
2463
- const defaultWidgetOptions$i = {
2464
- value: 0,
2465
- simplify: "required",
2466
- size: "normal",
2467
- inexact: false,
2468
- maxError: 0.1,
2469
- answerType: "number",
2470
- rightAlign: false
2471
- };
2472
- const inputNumberWidgetLogic = {
2473
- name: "input-number",
2474
- defaultWidgetOptions: defaultWidgetOptions$i,
2475
- defaultAlignment: "inline-block"
2476
- };
2477
-
2478
- const defaultWidgetOptions$h = {
2479
- graph: {
2480
- box: [400, 400],
2481
- labels: ["x", "y"],
2482
- range: [[-10, 10], [-10, 10]],
2483
- tickStep: [1, 1],
2484
- gridStep: [1, 1],
2485
- markings: "graph"
2486
- },
2487
- elements: []
2488
- };
2489
- const interactionWidgetLogic = {
2490
- name: "interaction",
2491
- defaultWidgetOptions: defaultWidgetOptions$h
2492
- };
2493
-
2494
- const _excluded$7 = ["correct"];
2495
- function getInteractiveGraphPublicWidgetOptions(options) {
2496
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$7);
2497
- return publicOptions;
2498
- }
135
+ const stringToNumber=(rawValue,ctx)=>{if(typeof rawValue==="number"){return ctx.success(rawValue)}const parsedNumber=+rawValue;if(rawValue===""||isNaN(parsedNumber)){return ctx.failure("a number or numeric string",rawValue)}return ctx.success(parsedNumber)};
2499
136
 
2500
- const defaultWidgetOptions$g = {
2501
- labels: ["x", "y"],
2502
- range: [[-10, 10], [-10, 10]],
2503
- step: [1, 1],
2504
- backgroundImage: {
2505
- url: null
2506
- },
2507
- markings: "graph",
2508
- showTooltips: false,
2509
- showProtractor: false,
2510
- graph: {
2511
- type: "linear"
2512
- },
2513
- correct: {
2514
- type: "linear",
2515
- coords: null
2516
- }
2517
- };
2518
- const interactiveGraphWidgetLogic = {
2519
- name: "interactive-graph",
2520
- defaultWidgetOptions: defaultWidgetOptions$g,
2521
- getPublicWidgetOptions: getInteractiveGraphPublicWidgetOptions
2522
- };
2523
-
2524
- const _excluded$6 = ["answers"];
2525
- function getLabelImagePublicWidgetOptions(options) {
2526
- return _extends({}, options, {
2527
- markers: options.markers.map(getLabelImageMarkerPublicData)
2528
- });
2529
- }
2530
- function getLabelImageMarkerPublicData(marker) {
2531
- const publicData = _objectWithoutPropertiesLoose(marker, _excluded$6);
2532
- return publicData;
2533
- }
137
+ function emptyToZero(x){return x===""?0:x}const imageDimensionToNumber=pipeParsers(union(number).or(string).parser).then(convert(emptyToZero)).then(stringToNumber).parser;const dimensionOrUndefined=defaulted(imageDimensionToNumber,()=>undefined);const parsePerseusImageBackground=object({url:optional(nullable(string)),width:dimensionOrUndefined,height:dimensionOrUndefined,top:dimensionOrUndefined,left:dimensionOrUndefined,bottom:dimensionOrUndefined,scale:dimensionOrUndefined});
2534
138
 
2535
- const defaultWidgetOptions$f = {
2536
- choices: [],
2537
- imageAlt: "",
2538
- imageUrl: "",
2539
- imageWidth: 0,
2540
- imageHeight: 0,
2541
- markers: [],
2542
- multipleAnswers: false,
2543
- hideChoicesFromInstructions: false
2544
- };
2545
- const labelImageWidgetLogic = {
2546
- name: "label-image",
2547
- defaultWidgetOptions: defaultWidgetOptions$f,
2548
- getPublicWidgetOptions: getLabelImagePublicWidgetOptions
2549
- };
2550
-
2551
- const seededRNG = function seededRNG(seed) {
2552
- let randomSeed = seed;
2553
- return function () {
2554
- let seed = randomSeed;
2555
- seed = seed + 0x7ed55d16 + (seed << 12) & 0xffffffff;
2556
- seed = (seed ^ 0xc761c23c ^ seed >>> 19) & 0xffffffff;
2557
- seed = seed + 0x165667b1 + (seed << 5) & 0xffffffff;
2558
- seed = (seed + 0xd3a2646c ^ seed << 9) & 0xffffffff;
2559
- seed = seed + 0xfd7046c5 + (seed << 3) & 0xffffffff;
2560
- seed = (seed ^ 0xb55a4f09 ^ seed >>> 16) & 0xffffffff;
2561
- return (randomSeed = seed & 0xfffffff) / 0x10000000;
2562
- };
2563
- };
2564
- function shuffle(array, randomSeed, ensurePermuted = false) {
2565
- const shuffled = _.clone(array);
2566
- if (!shuffled.length || _.all(shuffled, function (value) {
2567
- return _.isEqual(value, shuffled[0]);
2568
- })) {
2569
- return shuffled;
2570
- }
2571
- let random;
2572
- if (typeof randomSeed === "function") {
2573
- random = randomSeed;
2574
- } else {
2575
- random = seededRNG(randomSeed);
2576
- }
2577
- do {
2578
- for (let top = shuffled.length; top > 0; top--) {
2579
- const newEnd = Math.floor(random() * top);
2580
- const temp = shuffled[newEnd];
2581
- shuffled[newEnd] = shuffled[top - 1];
2582
- shuffled[top - 1] = temp;
2583
- }
2584
- } while (ensurePermuted && _.isEqual(array, shuffled));
2585
- return shuffled;
2586
- }
2587
- const random = seededRNG(new Date().getTime() & 0xffffffff);
2588
-
2589
- const shuffleMatcher = props => {
2590
- const rng = seededRNG(props.problemNum);
2591
- let left;
2592
- if (!props.orderMatters) {
2593
- left = props.left;
2594
- } else {
2595
- left = shuffle(props.left, rng, true);
2596
- }
2597
- const right = shuffle(props.right, rng, true);
2598
- return {
2599
- left,
2600
- right
2601
- };
2602
- };
2603
- function shuffleMatcherWithRandom(data) {
2604
- let left;
2605
- if (!data.orderMatters) {
2606
- left = data.left;
2607
- } else {
2608
- left = shuffle(data.left, Math.random, true);
2609
- }
2610
- const right = shuffle(data.right, Math.random, true);
2611
- return {
2612
- left,
2613
- right
2614
- };
2615
- }
2616
- function getMatcherPublicWidgetOptions(options) {
2617
- const {
2618
- left,
2619
- right
2620
- } = shuffleMatcherWithRandom(options);
2621
- return _extends({}, options, {
2622
- left: left,
2623
- right: right
2624
- });
2625
- }
139
+ const pairOfNumbers$2=pair(number,number);const parseImageWidget=parseWidget(constant("image"),object({title:optional(string),caption:optional(string),alt:optional(string),backgroundImage:parsePerseusImageBackground,static:optional(boolean),labels:optional(array(object({content:string,alignment:string,coordinates:array(number)}))),range:optional(pair(pairOfNumbers$2,pairOfNumbers$2)),box:optional(pairOfNumbers$2)}));
2626
140
 
2627
- const defaultWidgetOptions$e = {
2628
- left: ["$x$", "$y$", "$z$"],
2629
- right: ["$1$", "$2$", "$3$"],
2630
- labels: ["test", "label"],
2631
- orderMatters: false,
2632
- padding: true
2633
- };
2634
- const matcherWidgetLogic = {
2635
- name: "matcher",
2636
- defaultWidgetOptions: defaultWidgetOptions$e,
2637
- getPublicWidgetOptions: getMatcherPublicWidgetOptions
2638
- };
2639
-
2640
- const _excluded$5 = ["answers"];
2641
- function getMatrixPublicWidgetOptions(options) {
2642
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$5);
2643
- return publicOptions;
2644
- }
141
+ const booleanToString=(rawValue,ctx)=>{if(typeof rawValue==="boolean"){return ctx.success(String(rawValue))}return ctx.failure("boolean",rawValue)};const parseInputNumberWidget=parseWidget(constant("input-number"),object({answerType:optional(enumeration("number","decimal","integer","rational","improper","mixed","percent","pi")),inexact:optional(boolean),maxError:optional(union(number).or(string).parser),rightAlign:optional(boolean),simplify:enumeration("required","optional","enforced"),size:enumeration("normal","small"),value:union(number).or(string).or(booleanToString).parser,customKeypad:optional(boolean)}));
2645
142
 
2646
- const defaultWidgetOptions$d = {
2647
- matrixBoardSize: [3, 3],
2648
- answers: [[]],
2649
- prefix: "",
2650
- suffix: "",
2651
- cursorPosition: [0, 0]
2652
- };
2653
- const matrixWidgetLogic = {
2654
- name: "matrix",
2655
- defaultWidgetOptions: defaultWidgetOptions$d,
2656
- getPublicWidgetOptions: getMatrixPublicWidgetOptions
2657
- };
2658
-
2659
- const _excluded$4 = ["imageUrl", "imageTop", "imageLeft"];
2660
- const currentVersion$1 = {
2661
- major: 1,
2662
- minor: 0
2663
- };
2664
- const widgetOptionsUpgrades = {
2665
- "1": v0options => {
2666
- const {
2667
- imageUrl,
2668
- imageTop,
2669
- imageLeft
2670
- } = v0options,
2671
- rest = _objectWithoutPropertiesLoose(v0options, _excluded$4);
2672
- return _extends({}, rest, {
2673
- image: {
2674
- url: imageUrl,
2675
- top: imageTop,
2676
- left: imageLeft
2677
- }
2678
- });
2679
- }
2680
- };
2681
- const defaultWidgetOptions$c = {
2682
- box: [480, 480],
2683
- image: {},
2684
- showProtractor: true,
2685
- showRuler: false,
2686
- rulerLabel: "",
2687
- rulerTicks: 10,
2688
- rulerPixels: 40,
2689
- rulerLength: 10
2690
- };
2691
-
2692
- const measurerWidgetLogic = {
2693
- name: "measurer",
2694
- version: currentVersion$1,
2695
- widgetOptionsUpgrades: widgetOptionsUpgrades,
2696
- defaultWidgetOptions: defaultWidgetOptions$c
2697
- };
2698
-
2699
- const _excluded$3 = ["correctX", "correctRel"];
2700
- function getNumberLinePublicWidgetOptions(options) {
2701
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$3);
2702
- return publicOptions;
2703
- }
143
+ const pairOfNumbers$1=pair(number,number);const stringOrEmpty=defaulted(string,()=>"");const parseKey=pipeParsers(optional(string)).then(convert(String)).parser;const parseFunctionElement=object({type:constant("function"),key:parseKey,options:object({value:string,funcName:string,rangeMin:string,rangeMax:string,color:string,strokeDasharray:string,strokeWidth:number})});const parseLabelElement=object({type:constant("label"),key:parseKey,options:object({label:string,color:string,coordX:string,coordY:string})});const parseLineElement=object({type:constant("line"),key:parseKey,options:object({color:string,startX:string,startY:string,endX:string,endY:string,strokeDasharray:string,strokeWidth:number,arrows:string})});const parseMovableLineElement=object({type:constant("movable-line"),key:parseKey,options:object({startX:string,startY:string,startSubscript:number,endX:string,endY:string,endSubscript:number,constraint:string,snap:number,constraintFn:string,constraintXMin:string,constraintXMax:string,constraintYMin:string,constraintYMax:string})});const parseMovablePointElement=object({type:constant("movable-point"),key:parseKey,options:object({startX:string,startY:string,varSubscript:number,constraint:string,snap:number,constraintFn:string,constraintXMin:stringOrEmpty,constraintXMax:stringOrEmpty,constraintYMin:stringOrEmpty,constraintYMax:stringOrEmpty})});const parseParametricElement=object({type:constant("parametric"),key:parseKey,options:object({x:string,y:string,rangeMin:string,rangeMax:string,color:string,strokeDasharray:string,strokeWidth:number})});const parsePointElement=object({type:constant("point"),key:parseKey,options:object({color:string,coordX:string,coordY:string})});const parseRectangleElement=object({type:constant("rectangle"),key:parseKey,options:object({color:string,coordX:string,coordY:string,width:string,height:string})});const parseInteractionWidget=parseWidget(constant("interaction"),object({static:defaulted(boolean,()=>false),graph:object({editableSettings:optional(array(enumeration("canvas","graph"))),box:pairOfNumbers$1,labels:array(string),range:pair(pairOfNumbers$1,pairOfNumbers$1),gridStep:pairOfNumbers$1,markings:enumeration("graph","grid","none"),snapStep:optional(pairOfNumbers$1),valid:optional(union(boolean).or(string).parser),backgroundImage:optional(parsePerseusImageBackground),showProtractor:optional(boolean),showRuler:optional(boolean),rulerLabel:optional(string),rulerTicks:optional(number),tickStep:pairOfNumbers$1}),elements:array(discriminatedUnionOn("type").withBranch("function",parseFunctionElement).withBranch("label",parseLabelElement).withBranch("line",parseLineElement).withBranch("movable-line",parseMovableLineElement).withBranch("movable-point",parseMovablePointElement).withBranch("parametric",parseParametricElement).withBranch("point",parsePointElement).withBranch("rectangle",parseRectangleElement).parser)}));
2704
144
 
2705
- const defaultWidgetOptions$b = {
2706
- range: [0, 10],
2707
- labelRange: [null, null],
2708
- labelStyle: "decimal",
2709
- labelTicks: true,
2710
- divisionRange: [1, 12],
2711
- numDivisions: 5,
2712
- snapDivisions: 2,
2713
- tickStep: null,
2714
- correctRel: "eq",
2715
- correctX: null,
2716
- initialX: null,
2717
- showTooltips: false
2718
- };
2719
- const numberLineWidgetLogic = {
2720
- name: "number-line",
2721
- defaultWidgetOptions: defaultWidgetOptions$b,
2722
- getPublicWidgetOptions: getNumberLinePublicWidgetOptions
2723
- };
2724
-
2725
- const _excluded$2 = ["answers"];
2726
- function getNumericInputAnswerPublicData(answer) {
2727
- const {
2728
- answerForms,
2729
- simplify,
2730
- status
2731
- } = answer;
2732
- return {
2733
- answerForms,
2734
- simplify,
2735
- status
2736
- };
2737
- }
2738
- function getNumericInputPublicWidgetOptions(options) {
2739
- const {
2740
- answers
2741
- } = options,
2742
- publicWidgetOptions = _objectWithoutPropertiesLoose(options, _excluded$2);
2743
- return _extends({}, publicWidgetOptions, {
2744
- answers: answers.map(getNumericInputAnswerPublicData)
2745
- });
2746
- }
145
+ const ItemExtras=["calculator","chi2Table","financialCalculatorMonthlyPayment","financialCalculatorTotalAmount","financialCalculatorTimeToPayOff","periodicTable","periodicTableWithKey","tTable","zTable"];const PerseusExpressionAnswerFormConsidered=["correct","wrong","ungraded"];const lockedFigureColorNames=["blue","green","grayH","purple","pink","orange","red"];const lockedFigureColors={blue:"#3D7586",green:"#447A53",grayH:"#3B3D45",purple:"#594094",pink:"#B25071",red:"#D92916",orange:"#946700"};const lockedFigureFillStyles={none:0,white:1,translucent:.4,solid:1};const plotterPlotTypes=["bar","line","pic","histogram","dotplot"];
2747
146
 
2748
- const defaultWidgetOptions$a = {
2749
- answers: [{
2750
- value: null,
2751
- status: "correct",
2752
- message: "",
2753
- simplify: "required",
2754
- answerForms: [],
2755
- strict: false,
2756
- maxError: null
2757
- }],
2758
- size: "normal",
2759
- coefficient: false,
2760
- labelText: "",
2761
- rightAlign: false
2762
- };
2763
- const numericInputWidgetLogic = {
2764
- name: "numeric-input",
2765
- defaultWidgetOptions: defaultWidgetOptions$a,
2766
- defaultAlignment: "inline-block",
2767
- getPublicWidgetOptions: getNumericInputPublicWidgetOptions
2768
- };
2769
-
2770
- function getOrdererPublicWidgetOptions(options) {
2771
- return {
2772
- options: options.options,
2773
- height: options.height,
2774
- layout: options.layout
2775
- };
2776
- }
147
+ const pairOfNumbers=pair(number,number);const parsePerseusGraphTypeAngle=object({type:constant("angle"),showAngles:optional(boolean),allowReflexAngles:optional(boolean),angleOffsetDeg:optional(number),snapDegrees:optional(number),match:optional(constant("congruent")),coords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))});const parsePerseusGraphTypeCircle=object({type:constant("circle"),center:optional(pairOfNumbers),radius:optional(number),startCoords:optional(object({center:pairOfNumbers,radius:number})),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeLinear=object({type:constant("linear"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeLinearSystem=object({type:constant("linear-system"),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeNone=object({type:constant("none")});const parsePerseusGraphTypePoint=object({type:constant("point"),numPoints:optional(union(number).or(constant("unlimited")).parser),coords:optional(nullable(array(pairOfNumbers))),startCoords:optional(array(pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphTypePolygon=object({type:constant("polygon"),numSides:optional(union(number).or(constant("unlimited")).parser),showAngles:optional(boolean),showSides:optional(boolean),snapTo:optional(enumeration("grid","angles","sides")),match:optional(enumeration("similar","congruent","approx","exact")),startCoords:optional(array(pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeQuadratic=object({type:constant("quadratic"),coords:optional(nullable(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers))),startCoords:optional(trio(pairOfNumbers,pairOfNumbers,pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeRay=object({type:constant("ray"),coords:optional(nullable(pair(pairOfNumbers,pairOfNumbers))),startCoords:optional(pair(pairOfNumbers,pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeSegment=object({type:constant("segment"),numSegments:optional(number),coords:optional(nullable(array(pair(pairOfNumbers,pairOfNumbers)))),startCoords:optional(array(pair(pairOfNumbers,pairOfNumbers))),coord:optional(pairOfNumbers)});const parsePerseusGraphTypeSinusoid=object({type:constant("sinusoid"),coords:optional(nullable(array(pairOfNumbers))),startCoords:optional(array(pairOfNumbers)),coord:optional(pairOfNumbers)});const parsePerseusGraphType=discriminatedUnionOn("type").withBranch("angle",parsePerseusGraphTypeAngle).withBranch("circle",parsePerseusGraphTypeCircle).withBranch("linear",parsePerseusGraphTypeLinear).withBranch("linear-system",parsePerseusGraphTypeLinearSystem).withBranch("none",parsePerseusGraphTypeNone).withBranch("point",parsePerseusGraphTypePoint).withBranch("polygon",parsePerseusGraphTypePolygon).withBranch("quadratic",parsePerseusGraphTypeQuadratic).withBranch("ray",parsePerseusGraphTypeRay).withBranch("segment",parsePerseusGraphTypeSegment).withBranch("sinusoid",parsePerseusGraphTypeSinusoid).parser;const parseLockedFigureColor=enumeration(...lockedFigureColorNames);const parseLockedFigureFillType=enumeration("none","white","translucent","solid");const parseLockedLineStyle=enumeration("solid","dashed");const parseLockedLabelType=object({type:constant("label"),coord:pairOfNumbers,text:string,color:parseLockedFigureColor,size:enumeration("small","medium","large")});const parseLockedPointType=object({type:constant("point"),coord:pairOfNumbers,color:parseLockedFigureColor,filled:boolean,labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedLineType=object({type:constant("line"),kind:enumeration("line","ray","segment"),points:pair(parseLockedPointType,parseLockedPointType),color:parseLockedFigureColor,lineStyle:parseLockedLineStyle,showPoint1:defaulted(boolean,()=>false),showPoint2:defaulted(boolean,()=>false),labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedVectorType=object({type:constant("vector"),points:pair(pairOfNumbers,pairOfNumbers),color:parseLockedFigureColor,labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedEllipseType=object({type:constant("ellipse"),center:pairOfNumbers,radius:pairOfNumbers,angle:number,color:parseLockedFigureColor,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedPolygonType=object({type:constant("polygon"),points:array(pairOfNumbers),color:parseLockedFigureColor,showVertices:boolean,fillStyle:parseLockedFigureFillType,strokeStyle:parseLockedLineStyle,labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedFunctionDomain=defaulted(pair(defaulted(number,()=>-Infinity),defaulted(number,()=>Infinity)),()=>[-Infinity,Infinity]);const parseLockedFunctionType=object({type:constant("function"),color:parseLockedFigureColor,strokeStyle:parseLockedLineStyle,equation:string,directionalAxis:enumeration("x","y"),domain:parseLockedFunctionDomain,labels:optional(array(parseLockedLabelType)),ariaLabel:optional(string)});const parseLockedFigure=discriminatedUnionOn("type").withBranch("point",parseLockedPointType).withBranch("line",parseLockedLineType).withBranch("vector",parseLockedVectorType).withBranch("ellipse",parseLockedEllipseType).withBranch("polygon",parseLockedPolygonType).withBranch("function",parseLockedFunctionType).withBranch("label",parseLockedLabelType).parser;const parseInteractiveGraphWidget=parseWidget(constant("interactive-graph"),object({step:pairOfNumbers,gridStep:optional(pairOfNumbers),snapStep:optional(pairOfNumbers),backgroundImage:optional(parsePerseusImageBackground),markings:enumeration("graph","grid","none"),labels:optional(array(string)),showProtractor:boolean,showRuler:optional(boolean),showTooltips:optional(boolean),rulerLabel:optional(string),rulerTicks:optional(number),range:pair(pairOfNumbers,pairOfNumbers),graph:defaulted(parsePerseusGraphType,()=>({type:"linear"})),correct:parsePerseusGraphType,lockedFigures:optional(array(parseLockedFigure)),fullGraphLabel:optional(string),fullGraphAriaDescription:optional(string)}));
2777
148
 
2778
- const defaultWidgetOptions$9 = {
2779
- correctOptions: [{
2780
- content: "$x$"
2781
- }],
2782
- otherOptions: [{
2783
- content: "$y$"
2784
- }],
2785
- height: "normal",
2786
- layout: "horizontal"
2787
- };
2788
- const ordererWidgetLogic = {
2789
- name: "orderer",
2790
- defaultWidgetOptions: defaultWidgetOptions$9,
2791
- getPublicWidgetOptions: getOrdererPublicWidgetOptions
2792
- };
2793
-
2794
- const defaultWidgetOptions$8 = {
2795
- passageTitle: "",
2796
- passageText: "",
2797
- footnotes: "",
2798
- showLineNumbers: true
2799
- };
2800
- const passageWidgetLogic = {
2801
- name: "passage",
2802
- defaultWidgetOptions: defaultWidgetOptions$8
2803
- };
2804
-
2805
- const currentVersion = {
2806
- major: 0,
2807
- minor: 1
2808
- };
2809
- const defaultWidgetOptions$7 = {
2810
- passageNumber: 1,
2811
- referenceNumber: 1,
2812
- summaryText: ""
2813
- };
2814
-
2815
- const passageRefWidgetLogic = {
2816
- name: "passageRef",
2817
- version: currentVersion,
2818
- defaultWidgetOptions: defaultWidgetOptions$7,
2819
- defaultAlignment: "inline"
2820
- };
2821
-
2822
- const defaultWidgetOptions$6 = {
2823
- content: ""
2824
- };
2825
- const passageRefTargetWidgetLogic = {
2826
- name: "passageRefTarget",
2827
- defaultWidgetOptions: defaultWidgetOptions$6,
2828
- defaultAlignment: "inline"
2829
- };
2830
-
2831
- const defaultWidgetOptions$5 = {
2832
- url: "",
2833
- description: ""
2834
- };
2835
- const phetSimulationWidgetLogic = {
2836
- name: "phet-simulation",
2837
- defaultWidgetOptions: defaultWidgetOptions$5
2838
- };
2839
-
2840
- const _excluded$1 = ["correct"];
2841
- function getPlotterPublicWidgetOptions(options) {
2842
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded$1);
2843
- return publicOptions;
2844
- }
149
+ const parseLabelImageWidget=parseWidget(constant("label-image"),object({choices:array(string),imageUrl:string,imageAlt:string,imageHeight:number,imageWidth:number,markers:array(object({answers:array(string),label:string,x:number,y:number})),hideChoicesFromInstructions:boolean,multipleAnswers:boolean,static:defaulted(boolean,()=>false)}));
2845
150
 
2846
- const defaultWidgetOptions$4 = {
2847
- scaleY: 1,
2848
- maxY: 10,
2849
- snapsPerLine: 2,
2850
- correct: [1],
2851
- starting: [1],
2852
- type: "bar",
2853
- labels: ["", ""],
2854
- categories: [""],
2855
- picSize: 30,
2856
- picBoxHeight: 36,
2857
- plotDimensions: [275, 200],
2858
- labelInterval: 1,
2859
- picUrl: null
2860
- };
2861
- const plotterWidgetLogic = {
2862
- name: "plotter",
2863
- defaultWidgetOptions: defaultWidgetOptions$4,
2864
- getPublicWidgetOptions: getPlotterPublicWidgetOptions
2865
- };
2866
-
2867
- const defaultWidgetOptions$3 = {
2868
- programID: "",
2869
- height: 400
2870
- };
2871
- const pythonProgramWidgetLogic = {
2872
- name: "python-program",
2873
- defaultWidgetOptions: defaultWidgetOptions$3
2874
- };
2875
-
2876
- function getRadioChoicePublicData(choice) {
2877
- const {
2878
- content,
2879
- isNoneOfTheAbove,
2880
- widgets
2881
- } = choice;
2882
- return {
2883
- content,
2884
- isNoneOfTheAbove,
2885
- widgets
2886
- };
2887
- }
2888
- function usesNumCorrect(multipleSelect, countChoices, numCorrect) {
2889
- return multipleSelect && countChoices && numCorrect;
2890
- }
2891
- function getRadioPublicWidgetOptions(options) {
2892
- const {
2893
- numCorrect,
2894
- choices,
2895
- multipleSelect,
2896
- countChoices
2897
- } = options;
2898
- return _extends({}, options, {
2899
- numCorrect: usesNumCorrect(multipleSelect, countChoices, numCorrect) ? numCorrect : undefined,
2900
- choices: choices.map(getRadioChoicePublicData)
2901
- });
2902
- }
151
+ const parseMatcherWidget=parseWidget(constant("matcher"),object({labels:array(string),left:array(string),right:array(string),orderMatters:boolean,padding:boolean}));
2903
152
 
2904
- const radioWidgetLogic = {
2905
- name: "radio",
2906
- version: currentVersion$3,
2907
- widgetOptionsUpgrades: widgetOptionsUpgrades$2,
2908
- defaultWidgetOptions: defaultWidgetOptions$v,
2909
- getPublicWidgetOptions: getRadioPublicWidgetOptions
2910
- };
2911
-
2912
- function getSorterPublicWidgetOptions(options) {
2913
- const shuffledCorrect = shuffle(options.correct, Math.random, true);
2914
- return _extends({}, options, {
2915
- correct: shuffledCorrect,
2916
- isCorrectShuffled: true
2917
- });
2918
- }
153
+ const numberOrString=union(number).or(string).parser;const numeric=pipeParsers(defaulted(numberOrString,()=>NaN)).then(stringToNumber).parser;const parseMatrixWidget=parseWidget(defaulted(constant("matrix"),()=>"matrix"),object({prefix:optional(string),suffix:optional(string),answers:array(array(numeric)),cursorPosition:optional(array(number)),matrixBoardSize:array(number),static:optional(boolean)}));
2919
154
 
2920
- const defaultWidgetOptions$2 = {
2921
- correct: ["$x$", "$y$", "$z$"],
2922
- layout: "horizontal",
2923
- padding: true
2924
- };
2925
- const sorterWidgetLogic = {
2926
- name: "sorter",
2927
- defaultWidgetOptions: defaultWidgetOptions$2,
2928
- getPublicWidgetOptions: getSorterPublicWidgetOptions
2929
- };
2930
-
2931
- const _excluded = ["answers"];
2932
- function getTablePublicWidgetOptions(options) {
2933
- const publicOptions = _objectWithoutPropertiesLoose(options, _excluded);
2934
- return publicOptions;
2935
- }
155
+ const parseMeasurerWidget=parseWidget(constant("measurer"),object({image:defaulted(parsePerseusImageBackground,()=>({url:null,top:0,left:0})),showProtractor:boolean,showRuler:boolean,rulerLabel:string,rulerTicks:number,rulerPixels:number,rulerLength:number,box:pair(number,number),static:defaulted(boolean,()=>false)}));
2936
156
 
2937
- const defaultRows = 4;
2938
- const defaultColumns = 1;
2939
- const answers = new Array(defaultRows).fill(0).map(() => new Array(defaultColumns).fill(""));
2940
- const defaultWidgetOptions$1 = {
2941
- headers: [""],
2942
- rows: defaultRows,
2943
- columns: defaultColumns,
2944
- answers: answers
2945
- };
2946
- const tableWidgetLogic = {
2947
- name: "table",
2948
- defaultWidgetOptions: defaultWidgetOptions$1,
2949
- getPublicWidgetOptions: getTablePublicWidgetOptions
2950
- };
2951
-
2952
- const defaultWidgetOptions = {
2953
- location: ""
2954
- };
2955
- const videoWidgetLogic = {
2956
- name: "video",
2957
- defaultWidgetOptions,
2958
- supportedAlignments: ["block", "float-left", "float-right", "full-width"],
2959
- defaultAlignment: "block"
2960
- };
2961
-
2962
- const widgets = {};
2963
- function registerWidget(type, logic) {
2964
- widgets[type] = logic;
2965
- }
2966
- function isWidgetRegistered(type) {
2967
- const widgetLogic = widgets[type];
2968
- return !!widgetLogic;
2969
- }
2970
- function getCurrentVersion(type) {
2971
- const widgetLogic = widgets[type];
2972
- return (widgetLogic == null ? void 0 : widgetLogic.version) || {
2973
- major: 0,
2974
- minor: 0
2975
- };
2976
- }
2977
- const getPublicWidgetOptionsFunction = name => {
2978
- var _widgets$name$getPubl, _widgets$name;
2979
- return (_widgets$name$getPubl = (_widgets$name = widgets[name]) == null ? void 0 : _widgets$name.getPublicWidgetOptions) != null ? _widgets$name$getPubl : i => i;
2980
- };
2981
- function getWidgetOptionsUpgrades(type) {
2982
- const widgetLogic = widgets[type];
2983
- return (widgetLogic == null ? void 0 : widgetLogic.widgetOptionsUpgrades) || {};
2984
- }
2985
- function getDefaultWidgetOptions(type) {
2986
- const widgetLogic = widgets[type];
2987
- return (widgetLogic == null ? void 0 : widgetLogic.defaultWidgetOptions) || {};
2988
- }
2989
- const getSupportedAlignments = type => {
2990
- var _widgetLogic$supporte;
2991
- const widgetLogic = widgets[type];
2992
- if (!(widgetLogic != null && (_widgetLogic$supporte = widgetLogic.supportedAlignments) != null && _widgetLogic$supporte[0])) {
2993
- return ["default"];
2994
- }
2995
- return widgetLogic == null ? void 0 : widgetLogic.supportedAlignments;
2996
- };
2997
- const getDefaultAlignment = type => {
2998
- const widgetLogic = widgets[type];
2999
- if (!(widgetLogic != null && widgetLogic.defaultAlignment)) {
3000
- return "block";
3001
- }
3002
- return widgetLogic.defaultAlignment;
3003
- };
3004
- registerWidget("categorizer", categorizerWidgetLogic);
3005
- registerWidget("cs-program", csProgramWidgetLogic);
3006
- registerWidget("definition", definitionWidgetLogic);
3007
- registerWidget("dropdown", dropdownWidgetLogic);
3008
- registerWidget("explanation", explanationWidgetLogic);
3009
- registerWidget("expression", expressionWidgetLogic);
3010
- registerWidget("graded-group", gradedGroupWidgetLogic);
3011
- registerWidget("graded-group-set", gradedGroupSetWidgetLogic);
3012
- registerWidget("grapher", grapherWidgetLogic);
3013
- registerWidget("group", groupWidgetLogic);
3014
- registerWidget("iframe", iframeWidgetLogic);
3015
- registerWidget("image", imageWidgetLogic);
3016
- registerWidget("input-number", inputNumberWidgetLogic);
3017
- registerWidget("interaction", interactionWidgetLogic);
3018
- registerWidget("interactive-graph", interactiveGraphWidgetLogic);
3019
- registerWidget("label-image", labelImageWidgetLogic);
3020
- registerWidget("matcher", matcherWidgetLogic);
3021
- registerWidget("matrix", matrixWidgetLogic);
3022
- registerWidget("measurer", measurerWidgetLogic);
3023
- registerWidget("number-line", numberLineWidgetLogic);
3024
- registerWidget("numeric-input", numericInputWidgetLogic);
3025
- registerWidget("orderer", ordererWidgetLogic);
3026
- registerWidget("passage", passageWidgetLogic);
3027
- registerWidget("passage-ref", passageRefWidgetLogic);
3028
- registerWidget("passage-ref-target", passageRefTargetWidgetLogic);
3029
- registerWidget("phet-simulation", phetSimulationWidgetLogic);
3030
- registerWidget("plotter", plotterWidgetLogic);
3031
- registerWidget("python-program", pythonProgramWidgetLogic);
3032
- registerWidget("radio", radioWidgetLogic);
3033
- registerWidget("sorter", sorterWidgetLogic);
3034
- registerWidget("table", tableWidgetLogic);
3035
- registerWidget("video", videoWidgetLogic);
157
+ const parseMoleculeRendererWidget=parseWidget(constant("molecule-renderer"),object({widgetId:string,rotationAngle:optional(number),smiles:optional(string)}));
158
+
159
+ const emptyStringToNull=pipeParsers(constant("")).then(convert(()=>null)).parser;const parseNumberLineWidget=parseWidget(constant("number-line"),object({range:array(number),labelRange:array(nullable(union(number).or(emptyStringToNull).parser)),labelStyle:string,labelTicks:boolean,isTickCtrl:optional(nullable(boolean)),divisionRange:array(number),numDivisions:optional(nullable(number)),snapDivisions:defaulted(number,()=>2),tickStep:optional(nullable(number)),correctRel:optional(nullable(string)),correctX:nullable(number),initialX:optional(nullable(number)),showTooltips:optional(boolean),static:defaulted(boolean,()=>false)}));
160
+
161
+ const parseMathFormat=enumeration("integer","mixed","improper","proper","decimal","percent","pi");const parseSimplify=pipeParsers(union(constant(null)).or(constant(undefined)).or(boolean).or(constant("required")).or(constant("correct")).or(constant("enforced")).or(constant("optional")).or(constant("accepted")).parser).then(convert(deprecatedSimplifyValuesToRequired)).parser;function deprecatedSimplifyValuesToRequired(simplify){switch(simplify){case "enforced":case "required":case "optional":return simplify;default:return "required"}}const parseNumericInputWidget=parseWidget(constant("numeric-input"),object({answers:array(object({message:string,value:optional(nullable(number)),status:string,answerForms:defaulted(array(parseMathFormat),()=>undefined),strict:boolean,maxError:optional(nullable(number)),simplify:parseSimplify})),labelText:optional(string),size:string,coefficient:defaulted(boolean,()=>false),rightAlign:optional(boolean),static:defaulted(boolean,()=>false),answerForms:optional(array(object({name:parseMathFormat,simplify:parseSimplify})))}));
162
+
163
+ function parseRenderer(rawValue,ctx){return parsePerseusRenderer(rawValue,ctx)}const largeToAuto=(height,ctx)=>{if(height==="large"){return ctx.success("auto")}return ctx.success(height)};const parseOrdererWidget=parseWidget(constant("orderer"),object({options:defaulted(array(parseRenderer),()=>[]),correctOptions:array(parseRenderer),otherOptions:array(parseRenderer),height:pipeParsers(enumeration("normal","auto","large")).then(largeToAuto).parser,layout:defaulted(enumeration("horizontal","vertical"),()=>"horizontal")}));
164
+
165
+ const parsePassageRefWidget=parseWidget(constant("passage-ref"),object({passageNumber:number,referenceNumber:number,summaryText:optional(string)}));
166
+
167
+ const parsePassageWidget=parseWidget(constant("passage"),object({footnotes:defaulted(string,()=>""),passageText:string,passageTitle:defaulted(string,()=>""),showLineNumbers:boolean,static:defaulted(boolean,()=>false)}));
168
+
169
+ const parsePhetSimulationWidget=parseWidget(constant("phet-simulation"),object({url:string,description:string}));
170
+
171
+ const parsePlotterWidget=parseWidget(constant("plotter"),object({labels:array(string),categories:array(string),type:enumeration(...plotterPlotTypes),maxY:number,scaleY:defaulted(number,()=>1),labelInterval:optional(nullable(number)),snapsPerLine:defaulted(number,()=>2),starting:array(number),correct:array(number),picUrl:optional(nullable(string)),picSize:optional(nullable(number)),picBoxHeight:optional(nullable(number)),plotDimensions:defaulted(array(number),()=>[380,300])}));
172
+
173
+ const parsePythonProgramWidget=parseWidget(constant("python-program"),object({programID:string,height:number}));
174
+
175
+ const currentVersion$3={major:2,minor:0};function deriveNumCorrect(options){const{choices,numCorrect}=options;return numCorrect??choices.filter(c=>c.correct).length}const widgetOptionsUpgrades$2={"2":v1props=>{const upgraded={...v1props,numCorrect:deriveNumCorrect(v1props)};return upgraded},"1":v0props=>{const{noneOfTheAbove,...rest}=v0props;if(noneOfTheAbove){throw new Error("radio widget v0 no longer supports auto noneOfTheAbove")}return {...rest,hasNoneOfTheAbove:false}}};const defaultWidgetOptions$v={choices:[{},{},{},{}],displayCount:null,randomize:false,hasNoneOfTheAbove:false,multipleSelect:false,countChoices:false,deselectEnabled:false};
176
+
177
+ const version2=optional(object({major:constant(2),minor:number}));const parseRadioWidgetV2=parseWidgetWithVersion(version2,constant("radio"),object({numCorrect:optional(number),choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx))})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));const version1=optional(object({major:constant(1),minor:number}));const parseRadioWidgetV1=parseWidgetWithVersion(version1,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>undefined)})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV1ToV2(widget){const{options}=widget;return {...widget,version:{major:2,minor:0},options:{...options,numCorrect:deriveNumCorrect(options)}}}const version0=optional(object({major:constant(0),minor:number}));const parseRadioWidgetV0=parseWidgetWithVersion(version0,constant("radio"),object({choices:array(object({content:defaulted(string,()=>""),clue:optional(string),correct:optional(boolean),isNoneOfTheAbove:optional(boolean),widgets:optional((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx))})),hasNoneOfTheAbove:optional(boolean),countChoices:optional(boolean),randomize:optional(boolean),multipleSelect:optional(boolean),deselectEnabled:optional(boolean),onePerLine:optional(boolean),displayCount:optional(any),noneOfTheAbove:optional(constant(false))}));function migrateV0ToV1(widget){const{options}=widget;const{noneOfTheAbove:_,...rest}=options;return {...widget,version:{major:1,minor:0},options:{...rest,hasNoneOfTheAbove:false}}}const parseRadioWidget=versionedWidgetOptions(2,parseRadioWidgetV2).withMigrationFrom(1,parseRadioWidgetV1,migrateV1ToV2).withMigrationFrom(0,parseRadioWidgetV0,migrateV0ToV1).parser;
178
+
179
+ const parseSorterWidget=parseWidget(constant("sorter"),object({correct:array(string),padding:boolean,layout:enumeration("horizontal","vertical")}));
180
+
181
+ const parseTableWidget=parseWidget(constant("table"),object({headers:array(string),rows:number,columns:number,answers:array(array(string))}));
182
+
183
+ const parseVideoWidget=parseWidget(constant("video"),object({location:string,static:optional(boolean)}));
184
+
185
+ const parseWidgetsMap=(rawValue,ctx)=>{if(!isObject(rawValue)){return ctx.failure("PerseusWidgetsMap",rawValue)}const widgetsMap={};for(const key of Object.keys(rawValue)){const entryResult=parseWidgetsMapEntry([key,rawValue[key]],widgetsMap,ctx.forSubtree(key));if(isFailure(entryResult)){return entryResult}}return ctx.success(widgetsMap)};const parseWidgetsMapEntry=([id,widget],widgetMap,ctx)=>{const idComponentsResult=parseWidgetIdComponents(id.split(" "),ctx.forSubtree("(widget ID)"));if(isFailure(idComponentsResult)){return idComponentsResult}const[type,n]=idComponentsResult.value;function parseAndAssign(key,parse){const widgetResult=parse(widget,ctx);if(isFailure(widgetResult)){return widgetResult}widgetMap[key]=widgetResult.value;return ctx.success(undefined)}switch(type){case "categorizer":return parseAndAssign(`categorizer ${n}`,parseCategorizerWidget);case "cs-program":return parseAndAssign(`cs-program ${n}`,parseCSProgramWidget);case "definition":return parseAndAssign(`definition ${n}`,parseDefinitionWidget);case "dropdown":return parseAndAssign(`dropdown ${n}`,parseDropdownWidget);case "explanation":return parseAndAssign(`explanation ${n}`,parseExplanationWidget);case "expression":return parseAndAssign(`expression ${n}`,parseExpressionWidget);case "grapher":return parseAndAssign(`grapher ${n}`,parseGrapherWidget);case "group":return parseAndAssign(`group ${n}`,parseGroupWidget);case "graded-group":return parseAndAssign(`graded-group ${n}`,parseGradedGroupWidget);case "graded-group-set":return parseAndAssign(`graded-group-set ${n}`,parseGradedGroupSetWidget);case "iframe":return parseAndAssign(`iframe ${n}`,parseIframeWidget);case "image":return parseAndAssign(`image ${n}`,parseImageWidget);case "input-number":return parseAndAssign(`input-number ${n}`,parseInputNumberWidget);case "interaction":return parseAndAssign(`interaction ${n}`,parseInteractionWidget);case "interactive-graph":return parseAndAssign(`interactive-graph ${n}`,parseInteractiveGraphWidget);case "label-image":return parseAndAssign(`label-image ${n}`,parseLabelImageWidget);case "matcher":return parseAndAssign(`matcher ${n}`,parseMatcherWidget);case "matrix":return parseAndAssign(`matrix ${n}`,parseMatrixWidget);case "measurer":return parseAndAssign(`measurer ${n}`,parseMeasurerWidget);case "molecule-renderer":return parseAndAssign(`molecule-renderer ${n}`,parseMoleculeRendererWidget);case "number-line":return parseAndAssign(`number-line ${n}`,parseNumberLineWidget);case "numeric-input":return parseAndAssign(`numeric-input ${n}`,parseNumericInputWidget);case "orderer":return parseAndAssign(`orderer ${n}`,parseOrdererWidget);case "passage":return parseAndAssign(`passage ${n}`,parsePassageWidget);case "passage-ref":return parseAndAssign(`passage-ref ${n}`,parsePassageRefWidget);case "passage-ref-target":return parseAndAssign(`passage-ref-target ${n}`,any);case "phet-simulation":return parseAndAssign(`phet-simulation ${n}`,parsePhetSimulationWidget);case "plotter":return parseAndAssign(`plotter ${n}`,parsePlotterWidget);case "python-program":return parseAndAssign(`python-program ${n}`,parsePythonProgramWidget);case "radio":return parseAndAssign(`radio ${n}`,parseRadioWidget);case "sorter":return parseAndAssign(`sorter ${n}`,parseSorterWidget);case "table":return parseAndAssign(`table ${n}`,parseTableWidget);case "video":return parseAndAssign(`video ${n}`,parseVideoWidget);case "sequence":return parseAndAssign(`sequence ${n}`,parseDeprecatedWidget);case "lights-puzzle":return parseAndAssign(`lights-puzzle ${n}`,parseDeprecatedWidget);case "simulator":return parseAndAssign(`simulator ${n}`,parseDeprecatedWidget);case "transformer":return parseAndAssign(`transformer ${n}`,parseDeprecatedWidget);default:return parseAndAssign(`${type} ${n}`,parseWidget(constant(type),any))}};const parseDeprecatedWidget=parseWidget((_,ctx)=>ctx.success("deprecated-standin"),object({}));const parseStringToNonNegativeInt=(rawValue,ctx)=>{if(typeof rawValue!=="string"||!/^(0|[1-9][0-9]*)$/.test(rawValue)){return ctx.failure("a string representing a non-negative integer",rawValue)}return ctx.success(+rawValue)};const parseWidgetIdComponents=pair(string,parseStringToNonNegativeInt);
186
+
187
+ const parsePerseusRenderer=defaulted(object({content:defaulted(string,()=>""),widgets:defaulted((rawVal,ctx)=>parseWidgetsMap(rawVal,ctx),()=>({})),images:parseImages,metadata:any}),()=>({content:"",widgets:{},images:{}}));
188
+
189
+ const parsePerseusArticle=union(parsePerseusRenderer).or(array(parsePerseusRenderer)).parser;
190
+
191
+ const parseHint=object({replace:defaulted(boolean,()=>undefined),content:string,widgets:defaulted(parseWidgetsMap,()=>({})),images:parseImages,metadata:any});
192
+
193
+ const parsePerseusAnswerArea=pipeParsers(defaulted(object({}),()=>({}))).then(convert(toAnswerArea)).parser;function toAnswerArea(raw){return {zTable:!!raw.zTable,calculator:!!raw.calculator,chi2Table:!!raw.chi2Table,financialCalculatorMonthlyPayment:!!raw.financialCalculatorMonthlyPayment,financialCalculatorTotalAmount:!!raw.financialCalculatorTotalAmount,financialCalculatorTimeToPayOff:!!raw.financialCalculatorTimeToPayOff,periodicTable:!!raw.periodicTable,periodicTableWithKey:!!raw.periodicTableWithKey,tTable:!!raw.tTable}}
194
+
195
+ const parsePerseusItem$1=object({question:parsePerseusRenderer,hints:defaulted(array(parseHint),()=>[]),answerArea:parsePerseusAnswerArea,itemDataVersion:optional(nullable(object({major:number,minor:number}))),answer:any});
196
+
197
+ function parsePerseusItem(json){if(isRealJSONParse(JSON.parse)){return JSON.parse(json)}throw new Error("Something went wrong.")}function parseAndMigratePerseusItem(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);const result=parse(object,parsePerseusItem$1);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function parseAndMigratePerseusArticle(json){throwErrorIfCheatingDetected();const object=JSON.parse(json);const result=parse(object,parsePerseusArticle);if(isFailure(result)){return failure({message:result.detail,invalidObject:object})}return result}function throwErrorIfCheatingDetected(){if(!isRealJSONParse(JSON.parse)){throw new Error("Something went wrong.")}}
198
+
199
+ const libName="@khanacademy/perseus-core";const libVersion="7.0.1";perseusUtils.addLibraryVersionToPerseusDebug(libName,libVersion);
200
+
201
+ const Errors=Object.freeze({Unknown:"Unknown",Internal:"Internal",InvalidInput:"InvalidInput",NotAllowed:"NotAllowed",TransientService:"TransientService",Service:"Service"});
202
+
203
+ class PerseusError extends Error{constructor(message,kind,options){super(message);this.kind=kind;this.metadata=options?.metadata;}}
204
+
205
+ const pluck=function(table,subKey){return ___default.default.object(___default.default.map(table,function(value,key){return [key,value[subKey]]}))};const mapObject=function(obj,lambda){const result={};Object.keys(obj).forEach(key=>{result[key]=lambda(obj[key],key);});return result};
206
+
207
+ function getCategorizerPublicWidgetOptions(options){return {items:options.items,categories:options.categories,randomizeItems:options.randomizeItems,static:options.static}}
208
+
209
+ const defaultWidgetOptions$u={items:[],categories:[],values:[],randomizeItems:false};const categorizerWidgetLogic={name:"categorizer",defaultWidgetOptions: defaultWidgetOptions$u,getPublicWidgetOptions:getCategorizerPublicWidgetOptions};
210
+
211
+ function getCSProgramPublicWidgetOptions(options){return options}
212
+
213
+ const DEFAULT_HEIGHT=400;const defaultWidgetOptions$t={programID:"",programType:null,settings:[{name:"",value:""}],showEditor:false,showButtons:false,height:DEFAULT_HEIGHT};const csProgramWidgetLogic={name:"cs-program",defaultWidgetOptions: defaultWidgetOptions$t,supportedAlignments:["block","full-width"],getPublicWidgetOptions:getCSProgramPublicWidgetOptions};
214
+
215
+ const defaultWidgetOptions$s={togglePrompt:"",definition:""};const definitionWidgetLogic={name:"definition",defaultWidgetOptions: defaultWidgetOptions$s,defaultAlignment:"inline"};
216
+
217
+ function getDropdownPublicWidgetOptions(options){return {choices:options.choices.map(choice=>({content:choice.content})),placeholder:options.placeholder,static:options.static,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel}}
218
+
219
+ const defaultWidgetOptions$r={placeholder:"",choices:[{content:"",correct:false}]};const dropdownWidgetLogic={name:"definition",defaultWidgetOptions: defaultWidgetOptions$r,defaultAlignment:"inline-block",getPublicWidgetOptions:getDropdownPublicWidgetOptions};
220
+
221
+ const defaultWidgetOptions$q={showPrompt:"Explain",hidePrompt:"Hide explanation",explanation:"explanation goes here\n\nmore explanation",widgets:{}};const explanationWidgetLogic={name:"explanation",defaultWidgetOptions: defaultWidgetOptions$q,defaultAlignment:"inline"};
222
+
223
+ const currentVersion$2={major:2,minor:0};const widgetOptionsUpgrades$1={"2":v1options=>{return {times:v1options.times,buttonSets:v1options.buttonSets,functions:v1options.functions,buttonsVisible:v1options.buttonsVisible,visibleLabel:v1options.visibleLabel,ariaLabel:v1options.ariaLabel,answerForms:v1options.answerForms,extraKeys:v1options.extraKeys||deriveExtraKeys(v1options)}},"1":v0options=>{return {times:v0options.times,buttonSets:v0options.buttonSets,functions:v0options.functions,buttonsVisible:v0options.buttonsVisible,visibleLabel:v0options.visibleLabel,ariaLabel:v0options.ariaLabel,extraKeys:v0options.extraKeys,answerForms:[{considered:"correct",form:v0options.form,simplify:v0options.simplify,value:v0options.value}]}}};const defaultWidgetOptions$p={answerForms:[],times:false,buttonSets:["basic"],functions:["f","g","h"]};
224
+
225
+ function getExpressionPublicWidgetOptions(options){return {buttonSets:options.buttonSets,functions:options.functions,times:options.times,visibleLabel:options.visibleLabel,ariaLabel:options.ariaLabel,buttonsVisible:options.buttonsVisible,extraKeys:options.extraKeys}}
226
+
227
+ const expressionWidgetLogic={name:"expression",version:currentVersion$2,widgetOptionsUpgrades:widgetOptionsUpgrades$1,defaultWidgetOptions:defaultWidgetOptions$p,defaultAlignment:"inline-block",getPublicWidgetOptions:getExpressionPublicWidgetOptions};
228
+
229
+ const defaultWidgetOptions$o={title:"",content:"",widgets:{},images:{},hint:null};const gradedGroupWidgetLogic={name:"graded-group",defaultWidgetOptions: defaultWidgetOptions$o};
230
+
231
+ const defaultWidgetOptions$n={gradedGroups:[]};const gradedGroupSetWidgetLogic={name:"graded-group-set",defaultWidgetOptions: defaultWidgetOptions$n};
232
+
233
+ function getGrapherPublicWidgetOptions(options){const{correct:_,...publicOptions}=options;return publicOptions}
234
+
235
+ const defaultWidgetOptions$m={graph:{labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:{url:null},markings:"graph",rulerLabel:"",rulerTicks:10,valid:true,showTooltips:false},correct:{type:"linear",coords:null},availableTypes:["linear"]};const grapherWidgetLogic={name:"grapher",defaultWidgetOptions: defaultWidgetOptions$m,getPublicWidgetOptions:getGrapherPublicWidgetOptions};
236
+
237
+ const defaultWidgetOptions$l={content:"",widgets:{},images:{}};const groupWidgetLogic={name:"group",defaultWidgetOptions: defaultWidgetOptions$l};
238
+
239
+ function getIFramePublicWidgetOptions(options){return options}
240
+
241
+ const defaultWidgetOptions$k={url:"",settings:[{name:"",value:""}],width:"400",height:"400",allowFullScreen:false,allowTopNavigation:false};const iframeWidgetLogic={name:"iframe",defaultWidgetOptions: defaultWidgetOptions$k,getPublicWidgetOptions:getIFramePublicWidgetOptions};
242
+
243
+ const defaultWidgetOptions$j={title:"",range:[[0,10],[0,10]],box:[400,400],backgroundImage:{url:null,width:0,height:0},labels:[],alt:"",caption:""};const imageWidgetLogic={name:"image",defaultWidgetOptions: defaultWidgetOptions$j,supportedAlignments:["block","full-width"],defaultAlignment:"block"};
244
+
245
+ const defaultWidgetOptions$i={value:0,simplify:"required",size:"normal",inexact:false,maxError:.1,answerType:"number",rightAlign:false};const inputNumberWidgetLogic={name:"input-number",defaultWidgetOptions: defaultWidgetOptions$i,defaultAlignment:"inline-block"};
246
+
247
+ const defaultWidgetOptions$h={graph:{box:[400,400],labels:["x","y"],range:[[-10,10],[-10,10]],tickStep:[1,1],gridStep:[1,1],markings:"graph"},elements:[]};const interactionWidgetLogic={name:"interaction",defaultWidgetOptions: defaultWidgetOptions$h};
248
+
249
+ function getInteractiveGraphPublicWidgetOptions(options){const{correct:_,...publicOptions}=options;return publicOptions}
250
+
251
+ const defaultWidgetOptions$g={labels:["x","y"],range:[[-10,10],[-10,10]],step:[1,1],backgroundImage:{url:null},markings:"graph",showTooltips:false,showProtractor:false,graph:{type:"linear"},correct:{type:"linear",coords:null}};const interactiveGraphWidgetLogic={name:"interactive-graph",defaultWidgetOptions: defaultWidgetOptions$g,getPublicWidgetOptions:getInteractiveGraphPublicWidgetOptions};
252
+
253
+ function getLabelImagePublicWidgetOptions(options){return {...options,markers:options.markers.map(getLabelImageMarkerPublicData)}}function getLabelImageMarkerPublicData(marker){const{answers:_,...publicData}=marker;return publicData}
254
+
255
+ const defaultWidgetOptions$f={choices:[],imageAlt:"",imageUrl:"",imageWidth:0,imageHeight:0,markers:[],multipleAnswers:false,hideChoicesFromInstructions:false};const labelImageWidgetLogic={name:"label-image",defaultWidgetOptions: defaultWidgetOptions$f,getPublicWidgetOptions:getLabelImagePublicWidgetOptions};
256
+
257
+ const seededRNG=function(seed){let randomSeed=seed;return function(){let seed=randomSeed;seed=seed+0x7ed55d16+(seed<<12)&0xffffffff;seed=(seed^0xc761c23c^seed>>>19)&0xffffffff;seed=seed+0x165667b1+(seed<<5)&0xffffffff;seed=(seed+0xd3a2646c^seed<<9)&0xffffffff;seed=seed+0xfd7046c5+(seed<<3)&0xffffffff;seed=(seed^0xb55a4f09^seed>>>16)&0xffffffff;return (randomSeed=seed&0xfffffff)/0x10000000}};function shuffle(array,randomSeed,ensurePermuted=false){const shuffled=___default.default.clone(array);if(!shuffled.length||___default.default.all(shuffled,function(value){return ___default.default.isEqual(value,shuffled[0])})){return shuffled}let random;if(typeof randomSeed==="function"){random=randomSeed;}else {random=seededRNG(randomSeed);}do{for(let top=shuffled.length;top>0;top--){const newEnd=Math.floor(random()*top);const temp=shuffled[newEnd];shuffled[newEnd]=shuffled[top-1];shuffled[top-1]=temp;}}while(ensurePermuted&&___default.default.isEqual(array,shuffled))return shuffled}const random=seededRNG(new Date().getTime()&0xffffffff);
258
+
259
+ const shuffleMatcher=props=>{const rng=seededRNG(props.problemNum);let left;if(!props.orderMatters){left=props.left;}else {left=shuffle(props.left,rng,true);}const right=shuffle(props.right,rng,true);return {left,right}};function shuffleMatcherWithRandom(data){let left;if(!data.orderMatters){left=data.left;}else {left=shuffle(data.left,Math.random,true);}const right=shuffle(data.right,Math.random,true);return {left,right}}function getMatcherPublicWidgetOptions(options){const{left,right}=shuffleMatcherWithRandom(options);return {...options,left:left,right:right}}
260
+
261
+ const defaultWidgetOptions$e={left:["$x$","$y$","$z$"],right:["$1$","$2$","$3$"],labels:["test","label"],orderMatters:false,padding:true};const matcherWidgetLogic={name:"matcher",defaultWidgetOptions: defaultWidgetOptions$e,getPublicWidgetOptions:getMatcherPublicWidgetOptions};
262
+
263
+ function getMatrixPublicWidgetOptions(options){const{answers:_,...publicOptions}=options;return publicOptions}
264
+
265
+ const defaultWidgetOptions$d={matrixBoardSize:[3,3],answers:[[]],prefix:"",suffix:"",cursorPosition:[0,0]};const matrixWidgetLogic={name:"matrix",defaultWidgetOptions: defaultWidgetOptions$d,getPublicWidgetOptions:getMatrixPublicWidgetOptions};
266
+
267
+ const currentVersion$1={major:1,minor:0};const widgetOptionsUpgrades={"1":v0options=>{const{imageUrl,imageTop,imageLeft,...rest}=v0options;return {...rest,image:{url:imageUrl,top:imageTop,left:imageLeft}}}};const defaultWidgetOptions$c={box:[480,480],image:{},showProtractor:true,showRuler:false,rulerLabel:"",rulerTicks:10,rulerPixels:40,rulerLength:10};
268
+
269
+ const measurerWidgetLogic={name:"measurer",version:currentVersion$1,widgetOptionsUpgrades:widgetOptionsUpgrades,defaultWidgetOptions:defaultWidgetOptions$c};
270
+
271
+ function getNumberLinePublicWidgetOptions(options){const{correctX:_,correctRel:__,...publicOptions}=options;return publicOptions}
272
+
273
+ const defaultWidgetOptions$b={range:[0,10],labelRange:[null,null],labelStyle:"decimal",labelTicks:true,divisionRange:[1,12],numDivisions:5,snapDivisions:2,tickStep:null,correctRel:"eq",correctX:null,initialX:null,showTooltips:false};const numberLineWidgetLogic={name:"number-line",defaultWidgetOptions: defaultWidgetOptions$b,getPublicWidgetOptions:getNumberLinePublicWidgetOptions};
274
+
275
+ function getNumericInputAnswerPublicData(answer){const{answerForms,simplify,status}=answer;return {answerForms,simplify,status}}function getNumericInputPublicWidgetOptions(options){const{answers,...publicWidgetOptions}=options;return {...publicWidgetOptions,answers:answers.map(getNumericInputAnswerPublicData)}}
276
+
277
+ const defaultWidgetOptions$a={answers:[{value:null,status:"correct",message:"",simplify:"required",answerForms:[],strict:false,maxError:null}],size:"normal",coefficient:false,labelText:"",rightAlign:false};const numericInputWidgetLogic={name:"numeric-input",defaultWidgetOptions: defaultWidgetOptions$a,defaultAlignment:"inline-block",getPublicWidgetOptions:getNumericInputPublicWidgetOptions};
278
+
279
+ function getOrdererPublicWidgetOptions(options){return {options:options.options,height:options.height,layout:options.layout}}
280
+
281
+ const defaultWidgetOptions$9={correctOptions:[{content:"$x$"}],otherOptions:[{content:"$y$"}],height:"normal",layout:"horizontal"};const ordererWidgetLogic={name:"orderer",defaultWidgetOptions: defaultWidgetOptions$9,getPublicWidgetOptions:getOrdererPublicWidgetOptions};
282
+
283
+ const defaultWidgetOptions$8={passageTitle:"",passageText:"",footnotes:"",showLineNumbers:true};const passageWidgetLogic={name:"passage",defaultWidgetOptions: defaultWidgetOptions$8};
284
+
285
+ const currentVersion={major:0,minor:1};const defaultWidgetOptions$7={passageNumber:1,referenceNumber:1,summaryText:""};
286
+
287
+ const passageRefWidgetLogic={name:"passageRef",version:currentVersion,defaultWidgetOptions:defaultWidgetOptions$7,defaultAlignment:"inline"};
288
+
289
+ const defaultWidgetOptions$6={content:""};const passageRefTargetWidgetLogic={name:"passageRefTarget",defaultWidgetOptions: defaultWidgetOptions$6,defaultAlignment:"inline"};
290
+
291
+ const defaultWidgetOptions$5={url:"",description:""};const phetSimulationWidgetLogic={name:"phet-simulation",defaultWidgetOptions: defaultWidgetOptions$5};
292
+
293
+ function getPlotterPublicWidgetOptions(options){const{correct:_,...publicOptions}=options;return publicOptions}
294
+
295
+ const defaultWidgetOptions$4={scaleY:1,maxY:10,snapsPerLine:2,correct:[1],starting:[1],type:"bar",labels:["",""],categories:[""],picSize:30,picBoxHeight:36,plotDimensions:[275,200],labelInterval:1,picUrl:null};const plotterWidgetLogic={name:"plotter",defaultWidgetOptions: defaultWidgetOptions$4,getPublicWidgetOptions:getPlotterPublicWidgetOptions};
296
+
297
+ const defaultWidgetOptions$3={programID:"",height:400};const pythonProgramWidgetLogic={name:"python-program",defaultWidgetOptions: defaultWidgetOptions$3};
298
+
299
+ function getRadioChoicePublicData(choice){const{content,isNoneOfTheAbove,widgets}=choice;return {content,isNoneOfTheAbove,widgets}}function usesNumCorrect(multipleSelect,countChoices,numCorrect){return multipleSelect&&countChoices&&numCorrect}function getRadioPublicWidgetOptions(options){const{numCorrect,choices,multipleSelect,countChoices}=options;return {...options,numCorrect:usesNumCorrect(multipleSelect,countChoices,numCorrect)?numCorrect:undefined,choices:choices.map(getRadioChoicePublicData)}}
300
+
301
+ const radioWidgetLogic={name:"radio",version:currentVersion$3,widgetOptionsUpgrades:widgetOptionsUpgrades$2,defaultWidgetOptions:defaultWidgetOptions$v,getPublicWidgetOptions:getRadioPublicWidgetOptions};
302
+
303
+ function getSorterPublicWidgetOptions(options){const shuffledCorrect=shuffle(options.correct,Math.random,true);return {...options,correct:shuffledCorrect,isCorrectShuffled:true}}
304
+
305
+ const defaultWidgetOptions$2={correct:["$x$","$y$","$z$"],layout:"horizontal",padding:true};const sorterWidgetLogic={name:"sorter",defaultWidgetOptions: defaultWidgetOptions$2,getPublicWidgetOptions:getSorterPublicWidgetOptions};
306
+
307
+ function getTablePublicWidgetOptions(options){const{answers:_,...publicOptions}=options;return publicOptions}
308
+
309
+ const defaultRows=4;const defaultColumns=1;const answers=new Array(defaultRows).fill(0).map(()=>new Array(defaultColumns).fill(""));const defaultWidgetOptions$1={headers:[""],rows:defaultRows,columns:defaultColumns,answers:answers};const tableWidgetLogic={name:"table",defaultWidgetOptions: defaultWidgetOptions$1,getPublicWidgetOptions:getTablePublicWidgetOptions};
310
+
311
+ const defaultWidgetOptions={location:""};const videoWidgetLogic={name:"video",defaultWidgetOptions,supportedAlignments:["block","float-left","float-right","full-width"],defaultAlignment:"block"};
312
+
313
+ const widgets={};function registerWidget(type,logic){widgets[type]=logic;}function isWidgetRegistered(type){const widgetLogic=widgets[type];return !!widgetLogic}function getCurrentVersion(type){const widgetLogic=widgets[type];return widgetLogic?.version||{major:0,minor:0}}const getPublicWidgetOptionsFunction=name=>{return widgets[name]?.getPublicWidgetOptions??(i=>i)};function getWidgetOptionsUpgrades(type){const widgetLogic=widgets[type];return widgetLogic?.widgetOptionsUpgrades||{}}function getDefaultWidgetOptions(type){const widgetLogic=widgets[type];return widgetLogic?.defaultWidgetOptions||{}}const getSupportedAlignments=type=>{const widgetLogic=widgets[type];if(!widgetLogic?.supportedAlignments?.[0]){return ["default"]}return widgetLogic?.supportedAlignments};const getDefaultAlignment=type=>{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);
3036
314
 
3037
315
  var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
3038
316
  __proto__: null,
@@ -3045,99 +323,93 @@ var coreWidgetRegistry = /*#__PURE__*/Object.freeze({
3045
323
  isWidgetRegistered: isWidgetRegistered
3046
324
  });
3047
325
 
3048
- const DEFAULT_STATIC = false;
3049
- const upgradeWidgetInfoToLatestVersion = oldWidgetInfo => {
3050
- const type = oldWidgetInfo.type;
3051
- if (!_.isString(type)) {
3052
- throw new PerseusError("widget type must be a string, but was: " + type, Errors.Internal);
3053
- }
3054
- if (!isWidgetRegistered(type)) {
3055
- return oldWidgetInfo;
3056
- }
3057
- const initialVersion = oldWidgetInfo.version || {
3058
- major: 0,
3059
- minor: 0
3060
- };
3061
- const latestVersion = getCurrentVersion(type);
3062
- if (initialVersion.major > latestVersion.major || initialVersion.major === latestVersion.major && initialVersion.minor > latestVersion.minor) {
3063
- return oldWidgetInfo;
3064
- }
3065
- let newEditorOptions = _.clone(oldWidgetInfo.options) || {};
3066
- const upgradePropsMap = getWidgetOptionsUpgrades(type);
3067
- if (_.keys(newEditorOptions).length !== 0) {
3068
- for (let nextVersion = initialVersion.major + 1; nextVersion <= latestVersion.major; nextVersion++) {
3069
- if (upgradePropsMap[String(nextVersion)]) {
3070
- newEditorOptions = upgradePropsMap[String(nextVersion)](newEditorOptions);
3071
- } else {
3072
- throw new PerseusError("No upgrade found for widget. Cannot render.", Errors.Internal, {
3073
- metadata: {
3074
- type,
3075
- fromMajorVersion: nextVersion - 1,
3076
- toMajorVersion: nextVersion,
3077
- oldWidgetInfo: JSON.stringify(oldWidgetInfo)
3078
- }
3079
- });
3080
- }
3081
- }
3082
- }
3083
- const defaultOptions = getDefaultWidgetOptions(type);
3084
- newEditorOptions = _extends({}, defaultOptions, newEditorOptions);
3085
- let alignment = oldWidgetInfo.alignment;
3086
- if (alignment == null || alignment === "default") {
3087
- var _getSupportedAlignmen;
3088
- alignment = (_getSupportedAlignmen = getSupportedAlignments(type)) == null ? void 0 : _getSupportedAlignmen[0];
3089
- if (!alignment) {
3090
- throw new PerseusError("No default alignment found when upgrading widget", Errors.Internal, {
3091
- metadata: {
3092
- widgetType: type
3093
- }
3094
- });
3095
- }
3096
- }
3097
- let widgetStatic = oldWidgetInfo.static;
3098
- if (widgetStatic == null) {
3099
- widgetStatic = DEFAULT_STATIC;
3100
- }
3101
- return _extends({}, oldWidgetInfo, {
3102
- version: latestVersion,
3103
- graded: oldWidgetInfo.graded != null ? oldWidgetInfo.graded : true,
3104
- alignment: alignment,
3105
- static: widgetStatic,
3106
- options: newEditorOptions
3107
- });
3108
- };
3109
- function getUpgradedWidgetOptions(oldWidgetOptions) {
3110
- return mapObject(oldWidgetOptions, (widgetInfo, widgetId) => {
3111
- if (!widgetInfo.type || !widgetInfo.alignment) {
3112
- const newValues = {};
3113
- if (!widgetInfo.type) {
3114
- newValues.type = widgetId.split(" ")[0];
3115
- }
3116
- if (!widgetInfo.alignment) {
3117
- newValues.alignment = "default";
3118
- }
3119
- widgetInfo = _extends({}, widgetInfo, newValues);
3120
- }
3121
- return upgradeWidgetInfoToLatestVersion(widgetInfo);
3122
- });
3123
- }
3124
-
3125
- function splitPerseusItem(originalItem) {
3126
- var _item$widgets;
3127
- const item = _.clone(originalItem);
3128
- const originalWidgets = (_item$widgets = item.widgets) != null ? _item$widgets : {};
3129
- const upgradedWidgets = getUpgradedWidgetOptions(originalWidgets);
3130
- const splitWidgets = {};
3131
- for (const [id, widget] of Object.entries(upgradedWidgets)) {
3132
- const publicWidgetOptionsFun = getPublicWidgetOptionsFunction(widget.type);
3133
- splitWidgets[id] = _extends({}, widget, {
3134
- options: publicWidgetOptionsFun(widget.options)
3135
- });
3136
- }
3137
- return _extends({}, item, {
3138
- widgets: splitWidgets
3139
- });
3140
- }
3141
-
3142
- export { coreWidgetRegistry as CoreWidgetRegistry, Errors, grapherUtil as GrapherUtil, ItemExtras, PerseusError, PerseusExpressionAnswerFormConsidered, addWidget, approximateDeepEqual, approximateEqual, categorizerWidgetLogic as categorizerLogic, csProgramWidgetLogic as csProgramLogic, deepClone, definitionWidgetLogic as definitionLogic, deriveExtraKeys, deriveNumCorrect, dropdownWidgetLogic as dropdownLogic, explanationWidgetLogic as explanationLogic, expressionWidgetLogic as expressionLogic, getCSProgramPublicWidgetOptions, getCategorizerPublicWidgetOptions, getDecimalSeparator, getDropdownPublicWidgetOptions, getExpressionPublicWidgetOptions, getGrapherPublicWidgetOptions, getIFramePublicWidgetOptions, getInteractiveGraphPublicWidgetOptions, getLabelImagePublicWidgetOptions, getMatcherPublicWidgetOptions, getMatrixPublicWidgetOptions, getMatrixSize, getNumberLinePublicWidgetOptions, getNumericInputPublicWidgetOptions, getOrdererPublicWidgetOptions, getPlotterPublicWidgetOptions, getRadioPublicWidgetOptions, getSorterPublicWidgetOptions, getTablePublicWidgetOptions, getUpgradedWidgetOptions, getWidgetIdsFromContent, getWidgetIdsFromContentByType, gradedGroupWidgetLogic as gradedGroupLogic, gradedGroupSetWidgetLogic as gradedGroupSetLogic, grapherWidgetLogic as grapherLogic, groupWidgetLogic as groupLogic, iframeWidgetLogic as iframeLogic, imageWidgetLogic as imageLogic, inputNumberWidgetLogic as inputNumberLogic, interactionWidgetLogic as interactionLogic, interactiveGraphWidgetLogic as interactiveGraphLogic, isFailure, isSuccess, labelImageWidgetLogic as labelImageLogic, libVersion, lockedFigureColorNames, lockedFigureColors, lockedFigureFillStyles, mapObject, matcherWidgetLogic as matcherLogic, matrixWidgetLogic as matrixLogic, measurerWidgetLogic as measurerLogic, numberLineWidgetLogic as numberLineLogic, numericInputWidgetLogic as numericInputLogic, ordererWidgetLogic as ordererLogic, parseAndMigratePerseusArticle, parseAndMigratePerseusItem, parsePerseusItem, passageWidgetLogic as passageLogic, passageRefWidgetLogic as passageRefLogic, passageRefTargetWidgetLogic as passageRefTargetLogic, phetSimulationWidgetLogic as phetSimulationLogic, plotterWidgetLogic as plotterLogic, plotterPlotTypes, pluck, pythonProgramWidgetLogic as pythonProgramLogic, radioWidgetLogic as radioLogic, random, seededRNG, shuffle, shuffleMatcher, sorterWidgetLogic as sorterLogic, splitPerseusItem, tableWidgetLogic as tableLogic, upgradeWidgetInfoToLatestVersion, usesNumCorrect, videoWidgetLogic as videoLogic };
326
+ const DEFAULT_STATIC=false;const upgradeWidgetInfoToLatestVersion=oldWidgetInfo=>{const type=oldWidgetInfo.type;if(!___default.default.isString(type)){throw new PerseusError("widget type must be a string, but was: "+type,Errors.Internal)}if(!isWidgetRegistered(type)){return oldWidgetInfo}const initialVersion=oldWidgetInfo.version||{major:0,minor:0};const latestVersion=getCurrentVersion(type);if(initialVersion.major>latestVersion.major||initialVersion.major===latestVersion.major&&initialVersion.minor>latestVersion.minor){return oldWidgetInfo}let newEditorOptions=___default.default.clone(oldWidgetInfo.options)||{};const upgradePropsMap=getWidgetOptionsUpgrades(type);if(___default.default.keys(newEditorOptions).length!==0){for(let nextVersion=initialVersion.major+1;nextVersion<=latestVersion.major;nextVersion++){if(upgradePropsMap[String(nextVersion)]){newEditorOptions=upgradePropsMap[String(nextVersion)](newEditorOptions);}else {throw new PerseusError("No upgrade found for widget. Cannot render.",Errors.Internal,{metadata:{type,fromMajorVersion:nextVersion-1,toMajorVersion:nextVersion,oldWidgetInfo:JSON.stringify(oldWidgetInfo)}})}}}const defaultOptions=getDefaultWidgetOptions(type);newEditorOptions={...defaultOptions,...newEditorOptions};let alignment=oldWidgetInfo.alignment;if(alignment==null||alignment==="default"){alignment=getSupportedAlignments(type)?.[0];if(!alignment){throw new PerseusError("No default alignment found when upgrading widget",Errors.Internal,{metadata:{widgetType:type}})}}let widgetStatic=oldWidgetInfo.static;if(widgetStatic==null){widgetStatic=DEFAULT_STATIC;}return {...oldWidgetInfo,version:latestVersion,graded:oldWidgetInfo.graded!=null?oldWidgetInfo.graded:true,alignment:alignment,static:widgetStatic,options:newEditorOptions}};function getUpgradedWidgetOptions(oldWidgetOptions){return mapObject(oldWidgetOptions,(widgetInfo,widgetId)=>{if(!widgetInfo.type||!widgetInfo.alignment){const newValues={};if(!widgetInfo.type){newValues.type=widgetId.split(" ")[0];}if(!widgetInfo.alignment){newValues.alignment="default";}widgetInfo={...widgetInfo,...newValues};}return upgradeWidgetInfoToLatestVersion(widgetInfo)})}
327
+
328
+ function splitPerseusItem(originalItem){const item=___default.default.clone(originalItem);const originalWidgets=item.widgets??{};const upgradedWidgets=getUpgradedWidgetOptions(originalWidgets);const splitWidgets={};for(const[id,widget]of Object.entries(upgradedWidgets)){const publicWidgetOptionsFun=getPublicWidgetOptionsFunction(widget.type);splitWidgets[id]={...widget,options:publicWidgetOptionsFun(widget.options)};}return {...item,widgets:splitWidgets}}
329
+
330
+ exports.CoreWidgetRegistry = coreWidgetRegistry;
331
+ exports.Errors = Errors;
332
+ exports.GrapherUtil = grapherUtil;
333
+ exports.ItemExtras = ItemExtras;
334
+ exports.PerseusError = PerseusError;
335
+ exports.PerseusExpressionAnswerFormConsidered = PerseusExpressionAnswerFormConsidered;
336
+ exports.addWidget = addWidget;
337
+ exports.approximateDeepEqual = approximateDeepEqual;
338
+ exports.approximateEqual = approximateEqual;
339
+ exports.categorizerLogic = categorizerWidgetLogic;
340
+ exports.csProgramLogic = csProgramWidgetLogic;
341
+ exports.deepClone = deepClone;
342
+ exports.definitionLogic = definitionWidgetLogic;
343
+ exports.deriveExtraKeys = deriveExtraKeys;
344
+ exports.deriveNumCorrect = deriveNumCorrect;
345
+ exports.dropdownLogic = dropdownWidgetLogic;
346
+ exports.explanationLogic = explanationWidgetLogic;
347
+ exports.expressionLogic = expressionWidgetLogic;
348
+ exports.getCSProgramPublicWidgetOptions = getCSProgramPublicWidgetOptions;
349
+ exports.getCategorizerPublicWidgetOptions = getCategorizerPublicWidgetOptions;
350
+ exports.getDecimalSeparator = getDecimalSeparator;
351
+ exports.getDropdownPublicWidgetOptions = getDropdownPublicWidgetOptions;
352
+ exports.getExpressionPublicWidgetOptions = getExpressionPublicWidgetOptions;
353
+ exports.getGrapherPublicWidgetOptions = getGrapherPublicWidgetOptions;
354
+ exports.getIFramePublicWidgetOptions = getIFramePublicWidgetOptions;
355
+ exports.getInteractiveGraphPublicWidgetOptions = getInteractiveGraphPublicWidgetOptions;
356
+ exports.getLabelImagePublicWidgetOptions = getLabelImagePublicWidgetOptions;
357
+ exports.getMatcherPublicWidgetOptions = getMatcherPublicWidgetOptions;
358
+ exports.getMatrixPublicWidgetOptions = getMatrixPublicWidgetOptions;
359
+ exports.getMatrixSize = getMatrixSize;
360
+ exports.getNumberLinePublicWidgetOptions = getNumberLinePublicWidgetOptions;
361
+ exports.getNumericInputPublicWidgetOptions = getNumericInputPublicWidgetOptions;
362
+ exports.getOrdererPublicWidgetOptions = getOrdererPublicWidgetOptions;
363
+ exports.getPlotterPublicWidgetOptions = getPlotterPublicWidgetOptions;
364
+ exports.getRadioPublicWidgetOptions = getRadioPublicWidgetOptions;
365
+ exports.getSorterPublicWidgetOptions = getSorterPublicWidgetOptions;
366
+ exports.getTablePublicWidgetOptions = getTablePublicWidgetOptions;
367
+ exports.getUpgradedWidgetOptions = getUpgradedWidgetOptions;
368
+ exports.getWidgetIdsFromContent = getWidgetIdsFromContent;
369
+ exports.getWidgetIdsFromContentByType = getWidgetIdsFromContentByType;
370
+ exports.gradedGroupLogic = gradedGroupWidgetLogic;
371
+ exports.gradedGroupSetLogic = gradedGroupSetWidgetLogic;
372
+ exports.grapherLogic = grapherWidgetLogic;
373
+ exports.groupLogic = groupWidgetLogic;
374
+ exports.iframeLogic = iframeWidgetLogic;
375
+ exports.imageLogic = imageWidgetLogic;
376
+ exports.inputNumberLogic = inputNumberWidgetLogic;
377
+ exports.interactionLogic = interactionWidgetLogic;
378
+ exports.interactiveGraphLogic = interactiveGraphWidgetLogic;
379
+ exports.isFailure = isFailure;
380
+ exports.isSuccess = isSuccess;
381
+ exports.labelImageLogic = labelImageWidgetLogic;
382
+ exports.libVersion = libVersion;
383
+ exports.lockedFigureColorNames = lockedFigureColorNames;
384
+ exports.lockedFigureColors = lockedFigureColors;
385
+ exports.lockedFigureFillStyles = lockedFigureFillStyles;
386
+ exports.mapObject = mapObject;
387
+ exports.matcherLogic = matcherWidgetLogic;
388
+ exports.matrixLogic = matrixWidgetLogic;
389
+ exports.measurerLogic = measurerWidgetLogic;
390
+ exports.numberLineLogic = numberLineWidgetLogic;
391
+ exports.numericInputLogic = numericInputWidgetLogic;
392
+ exports.ordererLogic = ordererWidgetLogic;
393
+ exports.parseAndMigratePerseusArticle = parseAndMigratePerseusArticle;
394
+ exports.parseAndMigratePerseusItem = parseAndMigratePerseusItem;
395
+ exports.parsePerseusItem = parsePerseusItem;
396
+ exports.passageLogic = passageWidgetLogic;
397
+ exports.passageRefLogic = passageRefWidgetLogic;
398
+ exports.passageRefTargetLogic = passageRefTargetWidgetLogic;
399
+ exports.phetSimulationLogic = phetSimulationWidgetLogic;
400
+ exports.plotterLogic = plotterWidgetLogic;
401
+ exports.plotterPlotTypes = plotterPlotTypes;
402
+ exports.pluck = pluck;
403
+ exports.pythonProgramLogic = pythonProgramWidgetLogic;
404
+ exports.radioLogic = radioWidgetLogic;
405
+ exports.random = random;
406
+ exports.seededRNG = seededRNG;
407
+ exports.shuffle = shuffle;
408
+ exports.shuffleMatcher = shuffleMatcher;
409
+ exports.sorterLogic = sorterWidgetLogic;
410
+ exports.splitPerseusItem = splitPerseusItem;
411
+ exports.tableLogic = tableWidgetLogic;
412
+ exports.upgradeWidgetInfoToLatestVersion = upgradeWidgetInfoToLatestVersion;
413
+ exports.usesNumCorrect = usesNumCorrect;
414
+ exports.videoLogic = videoWidgetLogic;
3143
415
  //# sourceMappingURL=index.js.map