@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/es/index.js +304 -0
- package/dist/es/index.js.map +1 -0
- package/dist/index.js +335 -3063
- package/dist/index.js.map +1 -1
- package/package.json +6 -13
package/dist/index.js
CHANGED
|
@@ -1,456 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
994
|
-
return (rawValue, ctx) => ctx.success(f(rawValue));
|
|
995
|
-
}
|
|
97
|
+
const parseImages=defaulted(record(string,object({width:number,height:number})),()=>({}));
|
|
996
98
|
|
|
997
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
1168
|
-
gradedGroups: array(parseGradedGroupWidgetOptions)
|
|
1169
|
-
}));
|
|
105
|
+
const parseDefinitionWidget=parseWidget(constant("definition"),object({togglePrompt:string,definition:string,static:defaulted(boolean,()=>false)}));
|
|
1170
106
|
|
|
1171
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2938
|
-
|
|
2939
|
-
const
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
};
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
const
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
}
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
const
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
function
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
};
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
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 =
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
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
|