@khanacademy/perseus 26.0.0 → 27.0.0
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.css +0 -10
- package/dist/es/index.js +647 -948
- package/dist/es/index.js.map +1 -1
- package/dist/index.css +0 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.js +648 -953
- package/dist/index.js.map +1 -1
- package/dist/perseus-types.d.ts +25 -12
- package/dist/renderer.d.ts +8 -1
- package/dist/types.d.ts +1 -0
- package/dist/widget-container.d.ts +1 -1
- package/dist/widgets/expression.d.ts +4 -2
- package/dist/widgets/interactive-graph.d.ts +0 -3
- package/dist/widgets/interactive-graphs/interactive-graph-question-builder.d.ts +2 -1
- package/dist/widgets/interactive-graphs/mafs-graph.d.ts +1 -0
- package/dist/widgets/interactive-graphs/reducer/initialize-graph-state.d.ts +3 -1
- package/dist/widgets/interactive-graphs/reducer/use-graph-config.d.ts +1 -0
- package/dist/widgets/interactive-graphs/stateful-mafs-graph.d.ts +1 -0
- package/package.json +5 -5
- package/dist/widgets/unit.d.ts +0 -85
package/dist/index.js
CHANGED
|
@@ -618,6 +618,7 @@ class InnerMathInput extends React__namespace.Component {
|
|
|
618
618
|
}), /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.Popover, {
|
|
619
619
|
opened: this.state.keypadOpen,
|
|
620
620
|
onClose: () => this.closeKeypad(),
|
|
621
|
+
portal: false,
|
|
621
622
|
dismissEnabled: true,
|
|
622
623
|
content: () => /*#__PURE__*/React__namespace.createElement(wonderBlocksPopover.PopoverContentCore, {
|
|
623
624
|
closeButtonVisible: true,
|
|
@@ -834,7 +835,7 @@ const denylist = [
|
|
|
834
835
|
// (technically the renderer still adds them)
|
|
835
836
|
"key", "ref",
|
|
836
837
|
// added by src/renderer.jsx
|
|
837
|
-
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets",
|
|
838
|
+
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets", "hintMode",
|
|
838
839
|
// added by src/editor.jsx, for widgets removing themselves
|
|
839
840
|
// this is soooo not the right place for this, but alas.
|
|
840
841
|
"onRemove",
|
|
@@ -19194,6 +19195,7 @@ const replaceDeprecatedWidgets = () => {
|
|
|
19194
19195
|
replaceWidget("reaction-diagram", "deprecated-standin");
|
|
19195
19196
|
replaceWidget("sequence", "deprecated-standin");
|
|
19196
19197
|
replaceWidget("simulator", "deprecated-standin");
|
|
19198
|
+
replaceWidget("unit-input", "deprecated-standin");
|
|
19197
19199
|
};
|
|
19198
19200
|
const registerEditors = editorsToRegister => {
|
|
19199
19201
|
editorsToRegister.forEach(editor => {
|
|
@@ -19227,6 +19229,7 @@ const replaceDeprecatedEditors = () => {
|
|
|
19227
19229
|
replaceEditor("reaction-diagram", "deprecated-standin");
|
|
19228
19230
|
replaceEditor("sequence", "deprecated-standin");
|
|
19229
19231
|
replaceEditor("simulator", "deprecated-standin");
|
|
19232
|
+
replaceEditor("unit-input", "deprecated-standin");
|
|
19230
19233
|
};
|
|
19231
19234
|
const getWidget = name => {
|
|
19232
19235
|
// TODO(alex): Consider referring to these as renderers to avoid
|
|
@@ -19789,6 +19792,7 @@ class Renderer extends React__namespace.Component {
|
|
|
19789
19792
|
findExternalWidgets: () => [],
|
|
19790
19793
|
alwaysUpdate: false,
|
|
19791
19794
|
reviewMode: false,
|
|
19795
|
+
hintMode: false,
|
|
19792
19796
|
serializedState: null,
|
|
19793
19797
|
onSerializedStateUpdated: () => {},
|
|
19794
19798
|
linterContext: PerseusLinter__namespace.linterContextDefault
|
|
@@ -20079,6 +20083,7 @@ class Renderer extends React__namespace.Component {
|
|
|
20079
20083
|
onBlur: ___default["default"].partial(this._onWidgetBlur, id),
|
|
20080
20084
|
findWidgets: this.findWidgets,
|
|
20081
20085
|
reviewModeRubric: reviewModeRubric,
|
|
20086
|
+
hintMode: this.props.hintMode,
|
|
20082
20087
|
onChange: function (newProps, cb) {
|
|
20083
20088
|
let silent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
20084
20089
|
_this._setWidgetProps(id, newProps, cb, silent);
|
|
@@ -28585,7 +28590,8 @@ const defaultGraphConfig = {
|
|
|
28585
28590
|
graphDimensionsInPixels: [1, 1],
|
|
28586
28591
|
width: 0,
|
|
28587
28592
|
height: 0,
|
|
28588
|
-
labels: []
|
|
28593
|
+
labels: [],
|
|
28594
|
+
hintMode: false
|
|
28589
28595
|
};
|
|
28590
28596
|
const GraphConfigContext = /*#__PURE__*/React.createContext(defaultGraphConfig);
|
|
28591
28597
|
function useGraphConfig() {
|
|
@@ -30070,8 +30076,6 @@ const ItemExtras = [
|
|
|
30070
30076
|
|
|
30071
30077
|
// prettier-ignore
|
|
30072
30078
|
|
|
30073
|
-
// prettier-ignore
|
|
30074
|
-
|
|
30075
30079
|
//prettier-ignore
|
|
30076
30080
|
|
|
30077
30081
|
// A background image applied to various widgets.
|
|
@@ -30597,6 +30601,16 @@ function useDraggable(args) {
|
|
|
30597
30601
|
const isKeyboard = type.includes("key");
|
|
30598
30602
|
if (isKeyboard) {
|
|
30599
30603
|
event?.preventDefault();
|
|
30604
|
+
|
|
30605
|
+
// When a key is held down, we see multiple "keydown" events,
|
|
30606
|
+
// followed by a single "keyup" event.
|
|
30607
|
+
// For a single keypress, we only see a "keydown" event, no
|
|
30608
|
+
// "keyup".
|
|
30609
|
+
// We never want to process the keyup event as an intent to
|
|
30610
|
+
// move so we bail on further processing here.
|
|
30611
|
+
if (type === "keyup") {
|
|
30612
|
+
return;
|
|
30613
|
+
}
|
|
30600
30614
|
const {
|
|
30601
30615
|
direction: yDownDirection,
|
|
30602
30616
|
altKey,
|
|
@@ -30697,7 +30711,8 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30697
30711
|
const {
|
|
30698
30712
|
range,
|
|
30699
30713
|
markings,
|
|
30700
|
-
showTooltips
|
|
30714
|
+
showTooltips,
|
|
30715
|
+
hintMode
|
|
30701
30716
|
} = useGraphConfig();
|
|
30702
30717
|
const {
|
|
30703
30718
|
point,
|
|
@@ -30742,7 +30757,7 @@ const MovablePointView = /*#__PURE__*/React.forwardRef((props, hitboxRef) => {
|
|
|
30742
30757
|
cursor
|
|
30743
30758
|
},
|
|
30744
30759
|
"data-testid": "movable-point",
|
|
30745
|
-
tabIndex: tabIndex(focusBehavior)
|
|
30760
|
+
tabIndex: hintMode ? -1 : tabIndex(focusBehavior)
|
|
30746
30761
|
}, /*#__PURE__*/React__namespace.createElement("circle", {
|
|
30747
30762
|
className: "movable-point-hitbox",
|
|
30748
30763
|
r: hitboxSizePx / 2,
|
|
@@ -30830,7 +30845,8 @@ const MovableLine = props => {
|
|
|
30830
30845
|
};
|
|
30831
30846
|
function useControlPoint(point, color, onMovePoint) {
|
|
30832
30847
|
const {
|
|
30833
|
-
snapStep
|
|
30848
|
+
snapStep,
|
|
30849
|
+
hintMode
|
|
30834
30850
|
} = useGraphConfig();
|
|
30835
30851
|
const [focused, setFocused] = React.useState(false);
|
|
30836
30852
|
const keyboardHandleRef = React.useRef(null);
|
|
@@ -30852,7 +30868,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30852
30868
|
const focusableHandle = /*#__PURE__*/React__namespace.createElement("g", {
|
|
30853
30869
|
"data-testid": "movable-point__focusable-handle",
|
|
30854
30870
|
className: "movable-point__focusable-handle",
|
|
30855
|
-
tabIndex: 0,
|
|
30871
|
+
tabIndex: hintMode ? -1 : 0,
|
|
30856
30872
|
ref: keyboardHandleRef,
|
|
30857
30873
|
onFocus: () => setFocused(true),
|
|
30858
30874
|
onBlur: () => setFocused(false)
|
|
@@ -30885,7 +30901,8 @@ const Line$1 = props => {
|
|
|
30885
30901
|
const {
|
|
30886
30902
|
range,
|
|
30887
30903
|
graphDimensionsInPixels,
|
|
30888
|
-
snapStep
|
|
30904
|
+
snapStep,
|
|
30905
|
+
hintMode
|
|
30889
30906
|
} = useGraphConfig();
|
|
30890
30907
|
let startExtend = undefined;
|
|
30891
30908
|
let endExtend = undefined;
|
|
@@ -30907,7 +30924,7 @@ const Line$1 = props => {
|
|
|
30907
30924
|
});
|
|
30908
30925
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement("g", {
|
|
30909
30926
|
ref: line,
|
|
30910
|
-
tabIndex: 0,
|
|
30927
|
+
tabIndex: hintMode ? -1 : 0,
|
|
30911
30928
|
className: "movable-line",
|
|
30912
30929
|
"data-testid": "movable-line",
|
|
30913
30930
|
style: {
|
|
@@ -31426,6 +31443,9 @@ const PolygonGraph = props => {
|
|
|
31426
31443
|
snapStep,
|
|
31427
31444
|
snapTo
|
|
31428
31445
|
} = props.graphState;
|
|
31446
|
+
const {
|
|
31447
|
+
hintMode
|
|
31448
|
+
} = useGraphConfig();
|
|
31429
31449
|
|
|
31430
31450
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
31431
31451
|
// think coords can be null.
|
|
@@ -31445,12 +31465,16 @@ const PolygonGraph = props => {
|
|
|
31445
31465
|
constrain: p => ["angles", "sides"].includes(snapToValue) ? p : snap(snapStep, p)
|
|
31446
31466
|
});
|
|
31447
31467
|
const active = hovered || focused || dragging;
|
|
31468
|
+
const lastMoveTime = React__namespace.useRef(0);
|
|
31448
31469
|
const lines = getLines(points);
|
|
31449
31470
|
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, /*#__PURE__*/React__namespace.createElement(mafs.Polygon, {
|
|
31450
31471
|
points: [...points],
|
|
31451
31472
|
color: "var(--movable-line-stroke-color)",
|
|
31452
31473
|
svgPolygonProps: {
|
|
31453
|
-
strokeWidth: active ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)"
|
|
31474
|
+
strokeWidth: active ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31475
|
+
style: {
|
|
31476
|
+
fill: "transparent"
|
|
31477
|
+
}
|
|
31454
31478
|
}
|
|
31455
31479
|
}), points.map((point, i) => {
|
|
31456
31480
|
const pt1 = points.at(i - 1);
|
|
@@ -31482,10 +31506,11 @@ const PolygonGraph = props => {
|
|
|
31482
31506
|
color: "transparent",
|
|
31483
31507
|
svgPolygonProps: {
|
|
31484
31508
|
ref,
|
|
31485
|
-
tabIndex: 0,
|
|
31509
|
+
tabIndex: hintMode ? -1 : 0,
|
|
31486
31510
|
strokeWidth: TARGET_SIZE,
|
|
31487
31511
|
style: {
|
|
31488
|
-
cursor: dragging ? "grabbing" : "grab"
|
|
31512
|
+
cursor: dragging ? "grabbing" : "grab",
|
|
31513
|
+
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31489
31514
|
},
|
|
31490
31515
|
onFocus: () => setFocused(true),
|
|
31491
31516
|
onBlur: () => setFocused(false),
|
|
@@ -31497,7 +31522,15 @@ const PolygonGraph = props => {
|
|
|
31497
31522
|
key: "point-" + i,
|
|
31498
31523
|
snapTo: snapTo,
|
|
31499
31524
|
point: point,
|
|
31500
|
-
onMove: destination =>
|
|
31525
|
+
onMove: destination => {
|
|
31526
|
+
const now = Date.now();
|
|
31527
|
+
const targetFPS = 40;
|
|
31528
|
+
const moveThresholdTime = 1000 / targetFPS;
|
|
31529
|
+
if (now - lastMoveTime.current > moveThresholdTime) {
|
|
31530
|
+
dispatch(actions.polygon.movePoint(i, destination));
|
|
31531
|
+
lastMoveTime.current = now;
|
|
31532
|
+
}
|
|
31533
|
+
}
|
|
31501
31534
|
})));
|
|
31502
31535
|
};
|
|
31503
31536
|
function getLines(points) {
|
|
@@ -31618,7 +31651,8 @@ function MovableCircle(props) {
|
|
|
31618
31651
|
onMove
|
|
31619
31652
|
} = props;
|
|
31620
31653
|
const {
|
|
31621
|
-
snapStep
|
|
31654
|
+
snapStep,
|
|
31655
|
+
hintMode
|
|
31622
31656
|
} = useGraphConfig();
|
|
31623
31657
|
const draggableRef = React.useRef(null);
|
|
31624
31658
|
const {
|
|
@@ -31633,7 +31667,7 @@ function MovableCircle(props) {
|
|
|
31633
31667
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31634
31668
|
return /*#__PURE__*/React__namespace.createElement("g", {
|
|
31635
31669
|
ref: draggableRef,
|
|
31636
|
-
tabIndex: 0,
|
|
31670
|
+
tabIndex: hintMode ? -1 : 0,
|
|
31637
31671
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31638
31672
|
}, /*#__PURE__*/React__namespace.createElement("ellipse", {
|
|
31639
31673
|
className: "focus-ring",
|
|
@@ -32037,7 +32071,8 @@ const MafsGraph = props => {
|
|
|
32037
32071
|
const {
|
|
32038
32072
|
state,
|
|
32039
32073
|
dispatch,
|
|
32040
|
-
labels
|
|
32074
|
+
labels,
|
|
32075
|
+
hintMode
|
|
32041
32076
|
} = props;
|
|
32042
32077
|
const [width, height] = props.box;
|
|
32043
32078
|
const tickStep = props.step;
|
|
@@ -32052,7 +32087,8 @@ const MafsGraph = props => {
|
|
|
32052
32087
|
graphDimensionsInPixels: props.box,
|
|
32053
32088
|
width,
|
|
32054
32089
|
height,
|
|
32055
|
-
labels
|
|
32090
|
+
labels,
|
|
32091
|
+
hintMode
|
|
32056
32092
|
}
|
|
32057
32093
|
}, /*#__PURE__*/React__namespace.createElement(wonderBlocksCore.View, {
|
|
32058
32094
|
className: "mafs-graph",
|
|
@@ -32063,7 +32099,8 @@ const MafsGraph = props => {
|
|
|
32063
32099
|
padding: "25px 25px 0 0",
|
|
32064
32100
|
boxSizing: "content-box",
|
|
32065
32101
|
marginLeft: "20px",
|
|
32066
|
-
marginBottom: "20px"
|
|
32102
|
+
marginBottom: "20px",
|
|
32103
|
+
pointerEvents: hintMode ? "none" : "auto"
|
|
32067
32104
|
}
|
|
32068
32105
|
}, /*#__PURE__*/React__namespace.createElement(LegacyGrid, {
|
|
32069
32106
|
box: props.box,
|
|
@@ -32094,7 +32131,7 @@ const MafsGraph = props => {
|
|
|
32094
32131
|
}), props.lockedFigures && /*#__PURE__*/React__namespace.createElement(GraphLockedLayer, {
|
|
32095
32132
|
lockedFigures: props.lockedFigures,
|
|
32096
32133
|
range: state.range
|
|
32097
|
-
}),
|
|
32134
|
+
}), props.showProtractor && /*#__PURE__*/React__namespace.createElement(Protractor, null), renderGraph({
|
|
32098
32135
|
state,
|
|
32099
32136
|
dispatch
|
|
32100
32137
|
})))));
|
|
@@ -33195,7 +33232,6 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33195
33232
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
33196
33233
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
33197
33234
|
const showSides = graph.type === "polygon" ? graph.showSides : null;
|
|
33198
|
-
const startCoords = graph.startCoords ?? null;
|
|
33199
33235
|
const originalPropsRef = React.useRef(props);
|
|
33200
33236
|
const latestPropsRef = wonderBlocksCore.useLatestRef(props);
|
|
33201
33237
|
React.useEffect(() => {
|
|
@@ -33206,7 +33242,7 @@ const StatefulMafsGraph = /*#__PURE__*/React__namespace.forwardRef((props, ref)
|
|
|
33206
33242
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
33207
33243
|
dispatch(reinitialize(latestPropsRef.current));
|
|
33208
33244
|
}
|
|
33209
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides,
|
|
33245
|
+
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
33210
33246
|
return /*#__PURE__*/React__namespace.createElement(MafsGraph, _extends({}, props, {
|
|
33211
33247
|
state: state,
|
|
33212
33248
|
dispatch: dispatch
|
|
@@ -33297,9 +33333,6 @@ class LegacyInteractiveGraph extends React__namespace.Component {
|
|
|
33297
33333
|
markings: "graph",
|
|
33298
33334
|
showTooltips: false,
|
|
33299
33335
|
showProtractor: false,
|
|
33300
|
-
showRuler: false,
|
|
33301
|
-
rulerLabel: "",
|
|
33302
|
-
rulerTicks: 10,
|
|
33303
33336
|
graph: {
|
|
33304
33337
|
type: "linear"
|
|
33305
33338
|
}
|
|
@@ -34462,9 +34495,6 @@ class LegacyInteractiveGraph extends React__namespace.Component {
|
|
|
34462
34495
|
markings: this.props.markings,
|
|
34463
34496
|
backgroundImage: this.props.backgroundImage,
|
|
34464
34497
|
showProtractor: this.props.showProtractor,
|
|
34465
|
-
showRuler: this.props.showRuler,
|
|
34466
|
-
rulerLabel: this.props.rulerLabel,
|
|
34467
|
-
rulerTicks: this.props.rulerTicks,
|
|
34468
34498
|
onMouseDown: onMouseDown,
|
|
34469
34499
|
onGraphieUpdated: this.setGraphie,
|
|
34470
34500
|
setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable,
|
|
@@ -34483,9 +34513,6 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
34483
34513
|
markings: "graph",
|
|
34484
34514
|
showTooltips: false,
|
|
34485
34515
|
showProtractor: false,
|
|
34486
|
-
showRuler: false,
|
|
34487
|
-
rulerLabel: "",
|
|
34488
|
-
rulerTicks: 10,
|
|
34489
34516
|
graph: {
|
|
34490
34517
|
type: "linear"
|
|
34491
34518
|
}
|
|
@@ -34514,7 +34541,8 @@ class InteractiveGraph extends React__namespace.Component {
|
|
|
34514
34541
|
gridStep: gridStep,
|
|
34515
34542
|
snapStep: snapStep,
|
|
34516
34543
|
box: box,
|
|
34517
|
-
showTooltips: !!this.props.showTooltips
|
|
34544
|
+
showTooltips: !!this.props.showTooltips,
|
|
34545
|
+
hintMode: this.props.hintMode
|
|
34518
34546
|
}));
|
|
34519
34547
|
}
|
|
34520
34548
|
return /*#__PURE__*/React__namespace.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -44203,921 +44231,6 @@ var Table$1 = {
|
|
|
44203
44231
|
isLintable: true
|
|
44204
44232
|
};
|
|
44205
44233
|
|
|
44206
|
-
var isObject = function (obj) {
|
|
44207
|
-
return obj === Object(obj);
|
|
44208
|
-
};
|
|
44209
|
-
var merge = function () {
|
|
44210
|
-
var obj = {};
|
|
44211
|
-
for (var i = 0; i < arguments.length; i++) {
|
|
44212
|
-
var source = arguments[i];
|
|
44213
|
-
if (source) {
|
|
44214
|
-
for (var prop in source) {
|
|
44215
|
-
obj[prop] = source[prop];
|
|
44216
|
-
}
|
|
44217
|
-
}
|
|
44218
|
-
}
|
|
44219
|
-
return obj;
|
|
44220
|
-
};
|
|
44221
|
-
var clone = function (obj) {
|
|
44222
|
-
if (!isObject(obj)) {
|
|
44223
|
-
return obj;
|
|
44224
|
-
}
|
|
44225
|
-
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
44226
|
-
};
|
|
44227
|
-
|
|
44228
|
-
/* TODO batch *all* mutations
|
|
44229
|
-
* idea: freeze / thaw implementations for all types
|
|
44230
|
-
* lens constructor thaws, freeze delegates to type's freeze
|
|
44231
|
-
*/
|
|
44232
|
-
|
|
44233
|
-
// equivalents, without requiring it
|
|
44234
|
-
// find the implementation to use for a given object
|
|
44235
|
-
var dispatch = function (x) {
|
|
44236
|
-
if (Array.isArray(x)) {
|
|
44237
|
-
return arr;
|
|
44238
|
-
} else if (isObject(x)) {
|
|
44239
|
-
return obj;
|
|
44240
|
-
} else if (typeof x === "string") {
|
|
44241
|
-
return str;
|
|
44242
|
-
}
|
|
44243
|
-
};
|
|
44244
|
-
|
|
44245
|
-
// This is underscore with a different name
|
|
44246
|
-
var lens = function (obj) {
|
|
44247
|
-
if (obj instanceof lens) {
|
|
44248
|
-
return obj;
|
|
44249
|
-
}
|
|
44250
|
-
if (!(this instanceof lens)) {
|
|
44251
|
-
return new lens(obj);
|
|
44252
|
-
}
|
|
44253
|
-
var ops = dispatch(obj);
|
|
44254
|
-
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
44255
|
-
};
|
|
44256
|
-
lens.prototype.freeze = function () {
|
|
44257
|
-
var obj = this._wrapped;
|
|
44258
|
-
var ops = dispatch(obj);
|
|
44259
|
-
return ops.freeze ? ops.freeze(obj) : obj;
|
|
44260
|
-
};
|
|
44261
|
-
lens.prototype.zoom = function (lensArr) {
|
|
44262
|
-
if (this._zoomStack === undefined) {
|
|
44263
|
-
this._zoomStack = [];
|
|
44264
|
-
}
|
|
44265
|
-
this._zoomStack.push({
|
|
44266
|
-
zoom: lensArr,
|
|
44267
|
-
wrapped: this._wrapped
|
|
44268
|
-
});
|
|
44269
|
-
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
44270
|
-
return this;
|
|
44271
|
-
};
|
|
44272
|
-
lens.prototype.deZoom = function () {
|
|
44273
|
-
var frame = this._zoomStack.pop();
|
|
44274
|
-
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
44275
|
-
return this;
|
|
44276
|
-
};
|
|
44277
|
-
lens.prototype.get = function (lensArr) {
|
|
44278
|
-
var obj = this._wrapped;
|
|
44279
|
-
for (var i = 0; i < lensArr.length; i++) {
|
|
44280
|
-
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
44281
|
-
}
|
|
44282
|
-
return obj;
|
|
44283
|
-
};
|
|
44284
|
-
lens.prototype.mod = function (lensArr, f) {
|
|
44285
|
-
var obj = this._wrapped;
|
|
44286
|
-
var newObj = clone(obj);
|
|
44287
|
-
var ops = dispatch(obj);
|
|
44288
|
-
if (lensArr.length === 0) {
|
|
44289
|
-
this._wrapped = f(this._wrapped);
|
|
44290
|
-
} else if (lensArr.length === 1) {
|
|
44291
|
-
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
44292
|
-
} else {
|
|
44293
|
-
var monocle = lensArr[0];
|
|
44294
|
-
var shortLens = lensArr.slice(1);
|
|
44295
|
-
|
|
44296
|
-
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
44297
|
-
|
|
44298
|
-
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
44299
|
-
this._wrapped = newObj;
|
|
44300
|
-
}
|
|
44301
|
-
return this;
|
|
44302
|
-
};
|
|
44303
|
-
|
|
44304
|
-
// TODO - move to individual files
|
|
44305
|
-
lens.prototype.merge = function (lensArr, props) {
|
|
44306
|
-
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
44307
|
-
return merge(oldProps, props);
|
|
44308
|
-
}).freeze();
|
|
44309
|
-
return this;
|
|
44310
|
-
};
|
|
44311
|
-
|
|
44312
|
-
// Lens must have length >= 1 or there would be nothing to return
|
|
44313
|
-
lens.prototype.del = function (lensArr) {
|
|
44314
|
-
var obj = this._wrapped;
|
|
44315
|
-
var ops = dispatch(obj);
|
|
44316
|
-
if (lensArr.length === 1) {
|
|
44317
|
-
this._wrapped = ops.del(obj, lensArr[0]);
|
|
44318
|
-
} else {
|
|
44319
|
-
var monocle = lensArr[0];
|
|
44320
|
-
var shortLens = lensArr.slice(1);
|
|
44321
|
-
var newObj = clone(obj);
|
|
44322
|
-
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
44323
|
-
this._wrapped = newObj;
|
|
44324
|
-
}
|
|
44325
|
-
return this;
|
|
44326
|
-
};
|
|
44327
|
-
lens.prototype.set = function (lensArr, set) {
|
|
44328
|
-
return this.mod(lensArr, function () {
|
|
44329
|
-
return set;
|
|
44330
|
-
});
|
|
44331
|
-
};
|
|
44332
|
-
|
|
44333
|
-
// ARRAY FUNCTIONS
|
|
44334
|
-
|
|
44335
|
-
const arr = {
|
|
44336
|
-
get: function (arr, monocle) {
|
|
44337
|
-
return arr[monocle];
|
|
44338
|
-
},
|
|
44339
|
-
set: function (arr, monocle, val) {
|
|
44340
|
-
var newArr = arr.splice();
|
|
44341
|
-
newArr[monocle] = val;
|
|
44342
|
-
return newArr;
|
|
44343
|
-
},
|
|
44344
|
-
mod: function (arr, monocle, f) {
|
|
44345
|
-
var newArr = arr.slice();
|
|
44346
|
-
newArr[monocle] = f(arr[monocle]);
|
|
44347
|
-
return newArr;
|
|
44348
|
-
},
|
|
44349
|
-
del: function (arr, monocle) {
|
|
44350
|
-
var newArr = arr.slice();
|
|
44351
|
-
newArr.splice(monocle, 1);
|
|
44352
|
-
return newArr;
|
|
44353
|
-
}
|
|
44354
|
-
};
|
|
44355
|
-
|
|
44356
|
-
/*
|
|
44357
|
-
// Lens must point to a member of an array. We'll insert into that array.
|
|
44358
|
-
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
44359
|
-
var obj = this._wrapped;
|
|
44360
|
-
|
|
44361
|
-
var arrLens = lensArr.slice(0, -1);
|
|
44362
|
-
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
44363
|
-
|
|
44364
|
-
var arrIdx = lensArr[lensArr.length-1];
|
|
44365
|
-
arr.splice(arrIdx, 0, toInsert);
|
|
44366
|
-
return lens(obj).set(arrLens, arr);
|
|
44367
|
-
};
|
|
44368
|
-
|
|
44369
|
-
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
44370
|
-
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
44371
|
-
var newLens = lensArr.slice();
|
|
44372
|
-
newLens[newLens.length-1] += 1;
|
|
44373
|
-
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
44374
|
-
};
|
|
44375
|
-
*/
|
|
44376
|
-
|
|
44377
|
-
// OBJECT FUNCTIONS
|
|
44378
|
-
|
|
44379
|
-
const obj = {
|
|
44380
|
-
get: function (obj, monocle) {
|
|
44381
|
-
return obj[monocle];
|
|
44382
|
-
},
|
|
44383
|
-
set: function (obj, monocle, val) {
|
|
44384
|
-
var newObj = clone(obj);
|
|
44385
|
-
newObj[monocle] = val;
|
|
44386
|
-
return newObj;
|
|
44387
|
-
},
|
|
44388
|
-
mod: function (obj, monocle, f) {
|
|
44389
|
-
var newObj = clone(obj);
|
|
44390
|
-
newObj[monocle] = f(obj[monocle]);
|
|
44391
|
-
return newObj;
|
|
44392
|
-
},
|
|
44393
|
-
del: function (obj, monocle) {
|
|
44394
|
-
var newObj = clone(obj);
|
|
44395
|
-
delete newObj[monocle];
|
|
44396
|
-
return newObj;
|
|
44397
|
-
}
|
|
44398
|
-
};
|
|
44399
|
-
|
|
44400
|
-
// STRING FUNCTIONS
|
|
44401
|
-
|
|
44402
|
-
const str = {
|
|
44403
|
-
get: function (arr, monocle) {
|
|
44404
|
-
return arr[monocle];
|
|
44405
|
-
},
|
|
44406
|
-
set: function (arr, monocle, val) {
|
|
44407
|
-
var newArr = arr.splice();
|
|
44408
|
-
newArr[monocle] = val;
|
|
44409
|
-
return newArr;
|
|
44410
|
-
},
|
|
44411
|
-
mod: function (arr, monocle, f) {
|
|
44412
|
-
var newArr = arr.splice();
|
|
44413
|
-
newArr[monocle] = f(arr[monocle]);
|
|
44414
|
-
return newArr;
|
|
44415
|
-
},
|
|
44416
|
-
del: function (arr, monocle) {
|
|
44417
|
-
var newArr = arr.slice();
|
|
44418
|
-
newArr.splice(monocle);
|
|
44419
|
-
return newArr;
|
|
44420
|
-
}
|
|
44421
|
-
};
|
|
44422
|
-
|
|
44423
|
-
/* eslint-disable eqeqeq, @typescript-eslint/no-unused-vars */
|
|
44424
|
-
/*
|
|
44425
|
-
* A class for formatting number to significant digits.
|
|
44426
|
-
* Copyright (C) 2001 Stephen Ostermiller
|
|
44427
|
-
* http://ostermiller.org/contact.pl?regarding?JavaScript+Significant+Figures
|
|
44428
|
-
*
|
|
44429
|
-
* This program is free software; you can redistribute it and/or modify
|
|
44430
|
-
* it under the terms of the GNU General Public License as published by
|
|
44431
|
-
* the Free Software Foundation; either version 2 of the License, or
|
|
44432
|
-
* (at your option) any later version.
|
|
44433
|
-
*
|
|
44434
|
-
* This program is distributed in the hope that it will be useful,
|
|
44435
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
44436
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
44437
|
-
* GNU General Public License for more details.
|
|
44438
|
-
*/
|
|
44439
|
-
|
|
44440
|
-
/**
|
|
44441
|
-
* An object tho both scans floating points to
|
|
44442
|
-
* determine the number of significant figures.
|
|
44443
|
-
* and can display a floating point using any number
|
|
44444
|
-
* of significant figures.
|
|
44445
|
-
*
|
|
44446
|
-
* @param s A string representation of a floating point.
|
|
44447
|
-
*/
|
|
44448
|
-
class SignificantFigures {
|
|
44449
|
-
order;
|
|
44450
|
-
mantissa;
|
|
44451
|
-
positive;
|
|
44452
|
-
sigFigs;
|
|
44453
|
-
sigDecs;
|
|
44454
|
-
constructor(s) {
|
|
44455
|
-
this.order = parseOrder(s);
|
|
44456
|
-
this.mantissa = parseMantissa(s);
|
|
44457
|
-
this.positive = parseSign(s);
|
|
44458
|
-
|
|
44459
|
-
/**
|
|
44460
|
-
* Get the number of significant figures this object uses.
|
|
44461
|
-
* Leading zeros are not significant. Traling zeros up to
|
|
44462
|
-
* and after the decimal point are significant.
|
|
44463
|
-
* Significant figures is good to know when the number is
|
|
44464
|
-
* used in multiplication.
|
|
44465
|
-
*
|
|
44466
|
-
* @return the number of significant figures.
|
|
44467
|
-
*/
|
|
44468
|
-
this.sigFigs = this.mantissa.length;
|
|
44469
|
-
|
|
44470
|
-
/**
|
|
44471
|
-
* Get the least significant decimal this object uses.
|
|
44472
|
-
* This is useful to know if a number is being used
|
|
44473
|
-
* in addition.
|
|
44474
|
-
* 400 - 2 the hundreds place (10^2) is the least significant decimal.
|
|
44475
|
-
* 75 - 0 the ones place (10^0) is the least significant decimal.
|
|
44476
|
-
* .543 - -3 the 1/1000's place (10^-3) is the least significant decimal.
|
|
44477
|
-
*
|
|
44478
|
-
* @return an integer representing the least significant decimal place.
|
|
44479
|
-
*/
|
|
44480
|
-
this.sigDecs = this.order - this.mantissa.length;
|
|
44481
|
-
}
|
|
44482
|
-
}
|
|
44483
|
-
|
|
44484
|
-
/**
|
|
44485
|
-
* Format a floating point for display using the specified
|
|
44486
|
-
* number of significant figures and least significant decimal.
|
|
44487
|
-
* Scientific notation may used by this method if this
|
|
44488
|
-
* object is very small, very large, has many significant
|
|
44489
|
-
* figures, or the number of significant figures would be
|
|
44490
|
-
* ambiguous in the output if scientific notation were not
|
|
44491
|
-
* used.
|
|
44492
|
-
*
|
|
44493
|
-
* @param f A floating point number that should be displayed
|
|
44494
|
-
* @param sigFigs desired number of significant figures (integer).
|
|
44495
|
-
* @param sigDecs the least significant decimal place (integer).
|
|
44496
|
-
* @param scientific true iff scientific notation should always be used.
|
|
44497
|
-
* @return a string of this object formatted correctly.
|
|
44498
|
-
*/
|
|
44499
|
-
function displaySigFigs(f, sigFigs, sigDecs, scientific) {
|
|
44500
|
-
const s = "" + f;
|
|
44501
|
-
let order = parseOrder(s);
|
|
44502
|
-
let mantissa = parseMantissa(s);
|
|
44503
|
-
let positive = parseSign(s);
|
|
44504
|
-
let add;
|
|
44505
|
-
let decAdd;
|
|
44506
|
-
let sigAdd;
|
|
44507
|
-
let zeroScientific = false;
|
|
44508
|
-
if (f == 0 || mantissa == "" || mantissa == "0") {
|
|
44509
|
-
mantissa = "";
|
|
44510
|
-
for (let i = 0; i < sigFigs; i++) {
|
|
44511
|
-
mantissa += "0";
|
|
44512
|
-
}
|
|
44513
|
-
order = sigFigs + sigDecs;
|
|
44514
|
-
if (sigDecs < 0 && -sigDecs >= sigFigs) {
|
|
44515
|
-
zeroScientific = true;
|
|
44516
|
-
}
|
|
44517
|
-
} else {
|
|
44518
|
-
decAdd = order - mantissa.length - sigDecs;
|
|
44519
|
-
sigAdd = sigFigs - mantissa.length;
|
|
44520
|
-
add = Math.min(sigAdd, decAdd);
|
|
44521
|
-
if (add < 0) {
|
|
44522
|
-
let rounded = round(mantissa, -add);
|
|
44523
|
-
if (rounded.length > mantissa.length + add) {
|
|
44524
|
-
order++;
|
|
44525
|
-
if (decAdd > sigAdd) {
|
|
44526
|
-
rounded = round(rounded, 1);
|
|
44527
|
-
}
|
|
44528
|
-
}
|
|
44529
|
-
mantissa = rounded;
|
|
44530
|
-
} else if (add > 0) {
|
|
44531
|
-
for (let i = 0; i < add; i++) {
|
|
44532
|
-
mantissa += "0";
|
|
44533
|
-
}
|
|
44534
|
-
}
|
|
44535
|
-
if (mantissa == "" || mantissa == "0") {
|
|
44536
|
-
mantissa = "0";
|
|
44537
|
-
positive = true;
|
|
44538
|
-
order = 1 + sigDecs;
|
|
44539
|
-
if (order != 0) {
|
|
44540
|
-
zeroScientific = true;
|
|
44541
|
-
}
|
|
44542
|
-
}
|
|
44543
|
-
}
|
|
44544
|
-
const useScientific = scientific || mantissa.length > 20 || order > 4 || order < -2 || order - mantissa.length > 0 && trailingZeros(mantissa) > 0 || zeroScientific;
|
|
44545
|
-
let returnVal = "";
|
|
44546
|
-
if (!positive) {
|
|
44547
|
-
returnVal += "-";
|
|
44548
|
-
}
|
|
44549
|
-
if (useScientific) {
|
|
44550
|
-
returnVal += mantissa.charAt(0);
|
|
44551
|
-
if (mantissa.length > 1) {
|
|
44552
|
-
returnVal += "." + mantissa.substring(1, mantissa.length);
|
|
44553
|
-
}
|
|
44554
|
-
if (order - 1 != 0) {
|
|
44555
|
-
returnVal += " x 10^" + (order - 1);
|
|
44556
|
-
}
|
|
44557
|
-
} else {
|
|
44558
|
-
let wholePart = "";
|
|
44559
|
-
let fractPart = "";
|
|
44560
|
-
let needDot = true;
|
|
44561
|
-
if (order > 0) {
|
|
44562
|
-
if (mantissa.length > order) {
|
|
44563
|
-
wholePart = mantissa.substring(0, order);
|
|
44564
|
-
fractPart = mantissa.substring(order, mantissa.length);
|
|
44565
|
-
} else {
|
|
44566
|
-
wholePart = mantissa;
|
|
44567
|
-
needDot = trailingZeros(mantissa) != 0;
|
|
44568
|
-
for (let i = 0; i < order - mantissa.length; i++) {
|
|
44569
|
-
wholePart += "0";
|
|
44570
|
-
}
|
|
44571
|
-
}
|
|
44572
|
-
} else {
|
|
44573
|
-
for (let i = 0; i < -order; i++) {
|
|
44574
|
-
fractPart += "0";
|
|
44575
|
-
}
|
|
44576
|
-
fractPart += mantissa;
|
|
44577
|
-
}
|
|
44578
|
-
returnVal += (wholePart == "" ? "0" : wholePart) + (needDot ? "." : "") + fractPart;
|
|
44579
|
-
}
|
|
44580
|
-
return returnVal;
|
|
44581
|
-
}
|
|
44582
|
-
|
|
44583
|
-
/**
|
|
44584
|
-
* Count the significant trailing zeros on this object.
|
|
44585
|
-
*
|
|
44586
|
-
* @return the number of trailing zeros
|
|
44587
|
-
*/
|
|
44588
|
-
function trailingZeros(mantissa) {
|
|
44589
|
-
let zeros = 0;
|
|
44590
|
-
for (let i = mantissa.length - 1; i >= 0; i--) {
|
|
44591
|
-
const c = mantissa.charAt(i);
|
|
44592
|
-
if (c == "0") {
|
|
44593
|
-
zeros++;
|
|
44594
|
-
} else {
|
|
44595
|
-
return zeros;
|
|
44596
|
-
}
|
|
44597
|
-
}
|
|
44598
|
-
return zeros;
|
|
44599
|
-
}
|
|
44600
|
-
|
|
44601
|
-
/**
|
|
44602
|
-
* Parse a string representation of a floating point
|
|
44603
|
-
* and pull out the sign.
|
|
44604
|
-
*
|
|
44605
|
-
* @param s the string representation of a floating point.
|
|
44606
|
-
* @return true iff this is a positive number
|
|
44607
|
-
*/
|
|
44608
|
-
function parseSign(s) {
|
|
44609
|
-
let beginning = true;
|
|
44610
|
-
let seenDot = false;
|
|
44611
|
-
let seenSomething = false;
|
|
44612
|
-
let zeros = "";
|
|
44613
|
-
let all = "";
|
|
44614
|
-
let pos = true;
|
|
44615
|
-
for (let i = 0; i < s.length; i++) {
|
|
44616
|
-
const c = s.charAt(i);
|
|
44617
|
-
if (c >= "1" && c <= "9") {
|
|
44618
|
-
all += zeros + c;
|
|
44619
|
-
zeros = "";
|
|
44620
|
-
seenSomething = true;
|
|
44621
|
-
beginning = false;
|
|
44622
|
-
} else if (c == "0") {
|
|
44623
|
-
if (seenDot) {
|
|
44624
|
-
if (seenSomething) {
|
|
44625
|
-
all += zeros + c;
|
|
44626
|
-
zeros = "";
|
|
44627
|
-
}
|
|
44628
|
-
} else {
|
|
44629
|
-
if (seenSomething) {
|
|
44630
|
-
zeros += c;
|
|
44631
|
-
}
|
|
44632
|
-
}
|
|
44633
|
-
beginning = false;
|
|
44634
|
-
} else if (!seenDot && c == ".") {
|
|
44635
|
-
all += zeros;
|
|
44636
|
-
zeros = "";
|
|
44637
|
-
seenDot = true;
|
|
44638
|
-
beginning = false;
|
|
44639
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44640
|
-
parseInt(s.substring(i + 1, s.length));
|
|
44641
|
-
i = s.length;
|
|
44642
|
-
} else if (beginning && (c == "+" || c == "-")) {
|
|
44643
|
-
if (c == "-") {
|
|
44644
|
-
pos = !pos;
|
|
44645
|
-
}
|
|
44646
|
-
}
|
|
44647
|
-
}
|
|
44648
|
-
if (all == "") {
|
|
44649
|
-
return true;
|
|
44650
|
-
}
|
|
44651
|
-
return pos;
|
|
44652
|
-
}
|
|
44653
|
-
|
|
44654
|
-
/**
|
|
44655
|
-
* Parse a string representation of a floating point
|
|
44656
|
-
* and pull out the mantissa.
|
|
44657
|
-
*
|
|
44658
|
-
* @param s the string representation of a floating point.
|
|
44659
|
-
* @return the mantissa of this number.
|
|
44660
|
-
*/
|
|
44661
|
-
function parseMantissa(s) {
|
|
44662
|
-
let seenDot = false;
|
|
44663
|
-
let seenSomething = false;
|
|
44664
|
-
let zeros = "";
|
|
44665
|
-
let leadZeros = "";
|
|
44666
|
-
let all = "";
|
|
44667
|
-
for (let i = 0; i < s.length; i++) {
|
|
44668
|
-
const c = s.charAt(i);
|
|
44669
|
-
if (c >= "1" && c <= "9") {
|
|
44670
|
-
all += zeros + c;
|
|
44671
|
-
zeros = "";
|
|
44672
|
-
seenSomething = true;
|
|
44673
|
-
} else if (c == "0") {
|
|
44674
|
-
if (seenDot) {
|
|
44675
|
-
if (seenSomething) {
|
|
44676
|
-
all += zeros + c;
|
|
44677
|
-
zeros = "";
|
|
44678
|
-
} else {
|
|
44679
|
-
leadZeros += c;
|
|
44680
|
-
}
|
|
44681
|
-
} else {
|
|
44682
|
-
if (seenSomething) {
|
|
44683
|
-
leadZeros += c;
|
|
44684
|
-
zeros += c;
|
|
44685
|
-
} else {
|
|
44686
|
-
leadZeros += c;
|
|
44687
|
-
}
|
|
44688
|
-
}
|
|
44689
|
-
} else if (!seenDot && c == ".") {
|
|
44690
|
-
all += zeros;
|
|
44691
|
-
zeros = "";
|
|
44692
|
-
seenDot = true;
|
|
44693
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44694
|
-
parseInt(s.substring(i + 1, s.length));
|
|
44695
|
-
i = s.length;
|
|
44696
|
-
} else ;
|
|
44697
|
-
}
|
|
44698
|
-
if (all == "") {
|
|
44699
|
-
return leadZeros;
|
|
44700
|
-
}
|
|
44701
|
-
return all;
|
|
44702
|
-
}
|
|
44703
|
-
|
|
44704
|
-
/**
|
|
44705
|
-
* Parse a string representation of a floating point
|
|
44706
|
-
* and pull out the exponent.
|
|
44707
|
-
*
|
|
44708
|
-
* @param s the string representation of a floating point.
|
|
44709
|
-
* @return (integer) the number after the e.
|
|
44710
|
-
*/
|
|
44711
|
-
function parseOrder(s) {
|
|
44712
|
-
let seenDot = false;
|
|
44713
|
-
let seenSomething = false;
|
|
44714
|
-
let zeros = "";
|
|
44715
|
-
let all = "";
|
|
44716
|
-
let decPlaces = 0;
|
|
44717
|
-
let totalDecs = 0;
|
|
44718
|
-
for (let i = 0; i < s.length; i++) {
|
|
44719
|
-
const c = s.charAt(i);
|
|
44720
|
-
if (c >= "1" && c <= "9") {
|
|
44721
|
-
all += zeros + c;
|
|
44722
|
-
zeros = "";
|
|
44723
|
-
seenSomething = true;
|
|
44724
|
-
if (!seenDot) {
|
|
44725
|
-
totalDecs++;
|
|
44726
|
-
decPlaces++;
|
|
44727
|
-
}
|
|
44728
|
-
} else if (c == "0") {
|
|
44729
|
-
if (seenDot) {
|
|
44730
|
-
if (seenSomething) {
|
|
44731
|
-
all += zeros + c;
|
|
44732
|
-
zeros = "";
|
|
44733
|
-
} else {
|
|
44734
|
-
decPlaces--;
|
|
44735
|
-
}
|
|
44736
|
-
} else {
|
|
44737
|
-
totalDecs++;
|
|
44738
|
-
if (seenSomething) {
|
|
44739
|
-
decPlaces++;
|
|
44740
|
-
zeros += c;
|
|
44741
|
-
}
|
|
44742
|
-
}
|
|
44743
|
-
} else if (!seenDot && c == ".") {
|
|
44744
|
-
all += zeros;
|
|
44745
|
-
zeros = "";
|
|
44746
|
-
seenDot = true;
|
|
44747
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44748
|
-
const raised = parseInt(s.substring(i + 1, s.length));
|
|
44749
|
-
decPlaces += raised;
|
|
44750
|
-
totalDecs += raised;
|
|
44751
|
-
i = s.length;
|
|
44752
|
-
} else ;
|
|
44753
|
-
}
|
|
44754
|
-
if (all == "") {
|
|
44755
|
-
return totalDecs;
|
|
44756
|
-
}
|
|
44757
|
-
return decPlaces;
|
|
44758
|
-
}
|
|
44759
|
-
|
|
44760
|
-
/**
|
|
44761
|
-
* Remove the specified number of digits from string by
|
|
44762
|
-
* rounding. Proper rounding rules for scientific purposes
|
|
44763
|
-
* are followed.
|
|
44764
|
-
* This method may cause an extra significant figure
|
|
44765
|
-
* to be added to the number. For example, if 999999
|
|
44766
|
-
* were rounded, A one would carry over and become
|
|
44767
|
-
* a significant figure. Those who call this method
|
|
44768
|
-
* should check for this and call round again if needed.
|
|
44769
|
-
*
|
|
44770
|
-
* @param mantissa A string representing an whole number of arbitrary length.
|
|
44771
|
-
* @param digits A number of digits to remove
|
|
44772
|
-
* @return A string represted the rounded version of mantissa
|
|
44773
|
-
*/
|
|
44774
|
-
function round(mantissa, digits) {
|
|
44775
|
-
const last = mantissa.length - digits - 1;
|
|
44776
|
-
if (last < 0) {
|
|
44777
|
-
return "";
|
|
44778
|
-
}
|
|
44779
|
-
if (last >= mantissa.length - 1) {
|
|
44780
|
-
return mantissa;
|
|
44781
|
-
}
|
|
44782
|
-
const nextToLast = mantissa.charAt(last + 1);
|
|
44783
|
-
const lastChar = mantissa.charAt(last);
|
|
44784
|
-
let roundUp = false;
|
|
44785
|
-
if (nextToLast > "5") {
|
|
44786
|
-
roundUp = true;
|
|
44787
|
-
} else if (nextToLast == "5") {
|
|
44788
|
-
for (let j = last + 2; j < mantissa.length; j++) {
|
|
44789
|
-
if (mantissa.charAt(j) != "0") {
|
|
44790
|
-
roundUp = true;
|
|
44791
|
-
}
|
|
44792
|
-
}
|
|
44793
|
-
// @ts-expect-error - TS2362 - The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
|
|
44794
|
-
if (lastChar % 2 == 1) {
|
|
44795
|
-
roundUp = true;
|
|
44796
|
-
}
|
|
44797
|
-
}
|
|
44798
|
-
let result = "";
|
|
44799
|
-
for (let i = last; i >= 0; i--) {
|
|
44800
|
-
const c = mantissa.charAt(i);
|
|
44801
|
-
if (roundUp) {
|
|
44802
|
-
let nextChar;
|
|
44803
|
-
if (c == "9") {
|
|
44804
|
-
nextChar = "0";
|
|
44805
|
-
} else {
|
|
44806
|
-
switch (c) {
|
|
44807
|
-
case "0":
|
|
44808
|
-
nextChar = "1";
|
|
44809
|
-
break;
|
|
44810
|
-
case "1":
|
|
44811
|
-
nextChar = "2";
|
|
44812
|
-
break;
|
|
44813
|
-
case "2":
|
|
44814
|
-
nextChar = "3";
|
|
44815
|
-
break;
|
|
44816
|
-
case "3":
|
|
44817
|
-
nextChar = "4";
|
|
44818
|
-
break;
|
|
44819
|
-
case "4":
|
|
44820
|
-
nextChar = "5";
|
|
44821
|
-
break;
|
|
44822
|
-
case "5":
|
|
44823
|
-
nextChar = "6";
|
|
44824
|
-
break;
|
|
44825
|
-
case "6":
|
|
44826
|
-
nextChar = "7";
|
|
44827
|
-
break;
|
|
44828
|
-
case "7":
|
|
44829
|
-
nextChar = "8";
|
|
44830
|
-
break;
|
|
44831
|
-
case "8":
|
|
44832
|
-
nextChar = "9";
|
|
44833
|
-
break;
|
|
44834
|
-
}
|
|
44835
|
-
roundUp = false;
|
|
44836
|
-
}
|
|
44837
|
-
result = nextChar + result;
|
|
44838
|
-
} else {
|
|
44839
|
-
result = c + result;
|
|
44840
|
-
}
|
|
44841
|
-
}
|
|
44842
|
-
if (roundUp) {
|
|
44843
|
-
result = "1" + result;
|
|
44844
|
-
}
|
|
44845
|
-
return result;
|
|
44846
|
-
}
|
|
44847
|
-
|
|
44848
|
-
// TODO(joel): teach KAS how to accept an answer only if it's expressed in
|
|
44849
|
-
const ALL = "all";
|
|
44850
|
-
const countSigfigs = function (value) {
|
|
44851
|
-
return new SignificantFigures(value).sigFigs;
|
|
44852
|
-
};
|
|
44853
|
-
/* I just wrote this, but it's old by analogy to `OldExpression`, in that it's
|
|
44854
|
-
* the version that non-mathquill platforms get stuck with. Constructed with an
|
|
44855
|
-
* <input>, a parser, popsicle sticks, and glue.
|
|
44856
|
-
*
|
|
44857
|
-
* In the same way as OldExpression, this parses continuously as you type, then
|
|
44858
|
-
* shows and hides an error buddy. The error message is only shown after a
|
|
44859
|
-
* rolling two second delay, but hidden immediately on further typing.
|
|
44860
|
-
*/
|
|
44861
|
-
class OldUnitInput extends React__namespace.Component {
|
|
44862
|
-
static contextType = PerseusI18nContext;
|
|
44863
|
-
_errorTimeout;
|
|
44864
|
-
static defaultProps = {
|
|
44865
|
-
apiOptions: ApiOptions.defaults,
|
|
44866
|
-
value: ""
|
|
44867
|
-
};
|
|
44868
|
-
static validate(userInput, rubric, strings) {
|
|
44869
|
-
const answer = KAS__namespace.unitParse(rubric.value).expr;
|
|
44870
|
-
const guess = KAS__namespace.unitParse(userInput);
|
|
44871
|
-
if (!guess.parsed) {
|
|
44872
|
-
return {
|
|
44873
|
-
type: "invalid",
|
|
44874
|
-
message: strings.dontUnderstandUnits
|
|
44875
|
-
};
|
|
44876
|
-
}
|
|
44877
|
-
|
|
44878
|
-
// Note: we check sigfigs, then numerical correctness, then units, so
|
|
44879
|
-
// the most significant things come last, that way the user will see
|
|
44880
|
-
// the most important message.
|
|
44881
|
-
let message = null;
|
|
44882
|
-
|
|
44883
|
-
// did the user specify the right number of sigfigs?
|
|
44884
|
-
// TODO(joel) - add a grading mode where the wrong number of sigfigs
|
|
44885
|
-
// isn't marked wrong
|
|
44886
|
-
const sigfigs = rubric.sigfigs;
|
|
44887
|
-
const sigfigsCorrect = countSigfigs(guess.coefficient) === sigfigs;
|
|
44888
|
-
if (!sigfigsCorrect) {
|
|
44889
|
-
message = strings.checkSigFigs;
|
|
44890
|
-
}
|
|
44891
|
-
|
|
44892
|
-
// now we need to check that the answer is correct to the precision we
|
|
44893
|
-
// require.
|
|
44894
|
-
let numericallyCorrect;
|
|
44895
|
-
try {
|
|
44896
|
-
const x = new KAS__namespace.Var("x");
|
|
44897
|
-
const equality = new KAS__namespace.Eq(answer.simplify(), "=", new KAS__namespace.Mul(x, guess.expr.simplify()));
|
|
44898
|
-
const conversion = equality.solveLinearEquationForVariable(x);
|
|
44899
|
-
|
|
44900
|
-
// Make sure the conversion factor between the user's input answer
|
|
44901
|
-
// and the canonical answer is 1, to sigfig places.
|
|
44902
|
-
// TODO(joel) is this sound?
|
|
44903
|
-
numericallyCorrect = Number(conversion.eval()).toPrecision(sigfigs) === Number(1).toPrecision(sigfigs);
|
|
44904
|
-
} catch (e) {
|
|
44905
|
-
numericallyCorrect = false;
|
|
44906
|
-
}
|
|
44907
|
-
if (!numericallyCorrect) {
|
|
44908
|
-
message = strings.answerNumericallyIncorrect;
|
|
44909
|
-
}
|
|
44910
|
-
let kasCorrect;
|
|
44911
|
-
const guessUnit = primUnits(guess.expr.simplify());
|
|
44912
|
-
const answerUnit = primUnits(answer.simplify());
|
|
44913
|
-
if (rubric.accepting === ALL) {
|
|
44914
|
-
// We're accepting all units - KAS does the hard work of figuring
|
|
44915
|
-
// out if the user's unit is equivalent to the author's unit.
|
|
44916
|
-
kasCorrect = KAS__namespace.compare(guessUnit, answerUnit).equal;
|
|
44917
|
-
} else {
|
|
44918
|
-
// Are any of the accepted units the same as what the user entered?
|
|
44919
|
-
kasCorrect = ___default["default"](rubric.acceptingUnits).any(unit => {
|
|
44920
|
-
const thisAnswerUnit = primUnits(KAS__namespace.unitParse(unit).unit.simplify());
|
|
44921
|
-
return KAS__namespace.compare(thisAnswerUnit, guessUnit
|
|
44922
|
-
// TODO(joel) - make this work as intended.
|
|
44923
|
-
// { form: true }
|
|
44924
|
-
).equal;
|
|
44925
|
-
});
|
|
44926
|
-
}
|
|
44927
|
-
if (!kasCorrect) {
|
|
44928
|
-
message = strings.checkUnits;
|
|
44929
|
-
}
|
|
44930
|
-
const correct = kasCorrect && numericallyCorrect && sigfigsCorrect;
|
|
44931
|
-
return {
|
|
44932
|
-
type: "points",
|
|
44933
|
-
earned: correct ? 1 : 0,
|
|
44934
|
-
total: 1,
|
|
44935
|
-
message
|
|
44936
|
-
};
|
|
44937
|
-
}
|
|
44938
|
-
componentDidUpdate() {
|
|
44939
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44940
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44941
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44942
|
-
clearTimeout(this._errorTimeout);
|
|
44943
|
-
if (KAS__namespace.unitParse(this.props.value).parsed) {
|
|
44944
|
-
this._hideError();
|
|
44945
|
-
} else {
|
|
44946
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44947
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44948
|
-
// @ts-expect-error - TS2322 - Type 'Timeout' is not assignable to type 'number'.
|
|
44949
|
-
this._errorTimeout = setTimeout(this._showError, 2000);
|
|
44950
|
-
}
|
|
44951
|
-
}
|
|
44952
|
-
componentWillUnmount() {
|
|
44953
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44954
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44955
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44956
|
-
clearTimeout(this._errorTimeout);
|
|
44957
|
-
}
|
|
44958
|
-
_showError = () => {
|
|
44959
|
-
if (this.props.value === "") {
|
|
44960
|
-
return;
|
|
44961
|
-
}
|
|
44962
|
-
|
|
44963
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44964
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44965
|
-
const $error = $__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.error));
|
|
44966
|
-
// @ts-expect-error - TS2339 - Property 'is' does not exist on type 'JQueryStatic'.
|
|
44967
|
-
if (!$error.is(":visible")) {
|
|
44968
|
-
$error
|
|
44969
|
-
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
|
44970
|
-
.css({
|
|
44971
|
-
top: 50,
|
|
44972
|
-
opacity: 0.1
|
|
44973
|
-
}).show().animate({
|
|
44974
|
-
top: 0,
|
|
44975
|
-
opacity: 1.0
|
|
44976
|
-
}, 300);
|
|
44977
|
-
}
|
|
44978
|
-
};
|
|
44979
|
-
_hideError = () => {
|
|
44980
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44981
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44982
|
-
const $error = $__default["default"](ReactDOM__default["default"].findDOMNode(this.refs.error));
|
|
44983
|
-
// @ts-expect-error - TS2339 - Property 'is' does not exist on type 'JQueryStatic'.
|
|
44984
|
-
if ($error.is(":visible")) {
|
|
44985
|
-
// @ts-expect-error - TS2339 - Property 'animate' does not exist on type 'JQueryStatic'.
|
|
44986
|
-
$error.animate({
|
|
44987
|
-
top: 50,
|
|
44988
|
-
opacity: 0.1
|
|
44989
|
-
}, 300, function () {
|
|
44990
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
44991
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
44992
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
44993
|
-
$__default["default"](this).hide();
|
|
44994
|
-
});
|
|
44995
|
-
}
|
|
44996
|
-
};
|
|
44997
|
-
change = (() => {
|
|
44998
|
-
var _this = this;
|
|
44999
|
-
return function () {
|
|
45000
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
45001
|
-
args[_key] = arguments[_key];
|
|
45002
|
-
}
|
|
45003
|
-
// @ts-expect-error - TS2345 - Argument of type 'readonly any[]' is not assignable to parameter of type 'any[]'.
|
|
45004
|
-
return change.apply(_this, args);
|
|
45005
|
-
};
|
|
45006
|
-
})();
|
|
45007
|
-
handleBlur = () => {
|
|
45008
|
-
this.props.onBlur([]);
|
|
45009
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
45010
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
45011
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
45012
|
-
clearTimeout(this._errorTimeout);
|
|
45013
|
-
if (!KAS__namespace.unitParse(this.props.value).parsed) {
|
|
45014
|
-
this._showError();
|
|
45015
|
-
}
|
|
45016
|
-
};
|
|
45017
|
-
handleChange = event => {
|
|
45018
|
-
this._hideError();
|
|
45019
|
-
this.props.onChange({
|
|
45020
|
-
value: event.target.value
|
|
45021
|
-
});
|
|
45022
|
-
};
|
|
45023
|
-
simpleValidate = (rubric, onInputError) => {
|
|
45024
|
-
return OldUnitInput.validate(this.getUserInput(), rubric, this.context.strings);
|
|
45025
|
-
};
|
|
45026
|
-
getUserInput = () => {
|
|
45027
|
-
return this.props.value;
|
|
45028
|
-
};
|
|
45029
|
-
|
|
45030
|
-
// begin mobile stuff
|
|
45031
|
-
|
|
45032
|
-
getInputPaths = () => {
|
|
45033
|
-
// The widget itself is an input, so we return a single empty list to
|
|
45034
|
-
// indicate this.
|
|
45035
|
-
return [[]];
|
|
45036
|
-
};
|
|
45037
|
-
focusInputPath = inputPath => {
|
|
45038
|
-
// eslint-disable-next-line react/no-string-refs
|
|
45039
|
-
const input = ReactDOM__default["default"].findDOMNode(this.refs.input);
|
|
45040
|
-
if (input) {
|
|
45041
|
-
/**
|
|
45042
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
45043
|
-
* Change to using a ref callback so that focus() can be
|
|
45044
|
-
* accessed.
|
|
45045
|
-
*/
|
|
45046
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
45047
|
-
input.focus();
|
|
45048
|
-
}
|
|
45049
|
-
};
|
|
45050
|
-
handleFocus = () => {
|
|
45051
|
-
this.props.onFocus([]);
|
|
45052
|
-
};
|
|
45053
|
-
blurInputPath = inputPath => {
|
|
45054
|
-
// eslint-disable-next-line react/no-string-refs
|
|
45055
|
-
const input = ReactDOM__default["default"].findDOMNode(this.refs.input);
|
|
45056
|
-
if (input) {
|
|
45057
|
-
/**
|
|
45058
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
45059
|
-
* Change to using a ref callback so that focus() can be
|
|
45060
|
-
* accessed.
|
|
45061
|
-
*/
|
|
45062
|
-
// @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
45063
|
-
input.blur();
|
|
45064
|
-
}
|
|
45065
|
-
};
|
|
45066
|
-
setInputValue = (path, newValue, cb) => {
|
|
45067
|
-
this.props.onChange({
|
|
45068
|
-
value: newValue
|
|
45069
|
-
}, cb);
|
|
45070
|
-
};
|
|
45071
|
-
getDOMNodeForPath = () => {
|
|
45072
|
-
// eslint-disable-next-line react/no-string-refs
|
|
45073
|
-
return ReactDOM__default["default"].findDOMNode(this.refs.input);
|
|
45074
|
-
};
|
|
45075
|
-
getGrammarTypeForPath = inputPath => {
|
|
45076
|
-
return "unit";
|
|
45077
|
-
};
|
|
45078
|
-
|
|
45079
|
-
// end mobile stuff
|
|
45080
|
-
|
|
45081
|
-
// TODO(joel) think about showing the error buddy
|
|
45082
|
-
render() {
|
|
45083
|
-
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
45084
|
-
className: "old-unit-input"
|
|
45085
|
-
}, /*#__PURE__*/React__namespace.createElement("input", {
|
|
45086
|
-
onChange: this.handleChange,
|
|
45087
|
-
ref: "input" // eslint-disable-line react/no-string-refs
|
|
45088
|
-
,
|
|
45089
|
-
className: ClassNames.INTERACTIVE,
|
|
45090
|
-
value: this.props.value,
|
|
45091
|
-
onFocus: this.handleFocus,
|
|
45092
|
-
onBlur: this.handleBlur
|
|
45093
|
-
}), /*#__PURE__*/React__namespace.createElement("div", {
|
|
45094
|
-
ref: "error",
|
|
45095
|
-
className: "error",
|
|
45096
|
-
style: {
|
|
45097
|
-
display: "none"
|
|
45098
|
-
}
|
|
45099
|
-
}, this.context.strings.dontUnderstand));
|
|
45100
|
-
}
|
|
45101
|
-
}
|
|
45102
|
-
|
|
45103
|
-
// Extract the primitive units from a unit expression. This first simplifies
|
|
45104
|
-
// `expr` to a `Mul` like "5 kg m / s^2" then removes the first term.
|
|
45105
|
-
const primUnits = function (expr) {
|
|
45106
|
-
return expr.simplify().asMul().partition()[1].flatten().simplify();
|
|
45107
|
-
};
|
|
45108
|
-
var Unit = {
|
|
45109
|
-
name: "unit-input",
|
|
45110
|
-
displayName: "Unit input",
|
|
45111
|
-
defaultAlignment: "inline-block",
|
|
45112
|
-
widget: OldUnitInput,
|
|
45113
|
-
transform: x => lens(x).del(["value"]).freeze(),
|
|
45114
|
-
version: {
|
|
45115
|
-
major: 0,
|
|
45116
|
-
minor: 1
|
|
45117
|
-
},
|
|
45118
|
-
hidden: true
|
|
45119
|
-
};
|
|
45120
|
-
|
|
45121
44234
|
/**
|
|
45122
44235
|
* This is a component that adds a link to the transcript for embedded videos in articles.
|
|
45123
44236
|
*/
|
|
@@ -45292,7 +44405,7 @@ var Video$1 = {
|
|
|
45292
44405
|
};
|
|
45293
44406
|
|
|
45294
44407
|
/* eslint-disable import/no-named-as-default */
|
|
45295
|
-
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, PythonProgram$1, Sorter$1, Table$1,
|
|
44408
|
+
var extraWidgets = [Categorizer$1, CSProgram$1, Dropdown$1, Explanation$1, Definition$1, Grapher$1, GradedGroup$1, GradedGroupSet$1, Group$1, Iframe$1, Image$1, Interactive, InteractiveGraph$1, LabelImage$1, Matrix$1, Matcher$1, Measurer$1, Molecule$1, NumberLine$1, Orderer$1, Passage$1, PassageRef$1, PassageRefTarget$1, Plotter$1, PythonProgram$1, Sorter$1, Table$1, Video$1, DeprecatedStandin$1];
|
|
45296
44409
|
|
|
45297
44410
|
/**
|
|
45298
44411
|
* This should be called by all clients, specifying whether extra widgets are
|
|
@@ -45332,7 +44445,7 @@ const init = function (options) {
|
|
|
45332
44445
|
|
|
45333
44446
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
45334
44447
|
const libName = "@khanacademy/perseus";
|
|
45335
|
-
const libVersion = "
|
|
44448
|
+
const libVersion = "27.0.0";
|
|
45336
44449
|
perseusCore.addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
45337
44450
|
|
|
45338
44451
|
const apiVersion = {
|
|
@@ -45580,6 +44693,7 @@ class HintRenderer extends React__namespace.Component {
|
|
|
45580
44693
|
// eslint-disable-next-line react/no-string-refs
|
|
45581
44694
|
, {
|
|
45582
44695
|
ref: "renderer",
|
|
44696
|
+
hintMode: true,
|
|
45583
44697
|
widgets: hint.widgets,
|
|
45584
44698
|
content: hint.content || "",
|
|
45585
44699
|
images: hint.images,
|
|
@@ -46890,6 +46004,223 @@ function treeToItem(node) {
|
|
|
46890
46004
|
};
|
|
46891
46005
|
}
|
|
46892
46006
|
|
|
46007
|
+
var isObject = function (obj) {
|
|
46008
|
+
return obj === Object(obj);
|
|
46009
|
+
};
|
|
46010
|
+
var merge = function () {
|
|
46011
|
+
var obj = {};
|
|
46012
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
46013
|
+
var source = arguments[i];
|
|
46014
|
+
if (source) {
|
|
46015
|
+
for (var prop in source) {
|
|
46016
|
+
obj[prop] = source[prop];
|
|
46017
|
+
}
|
|
46018
|
+
}
|
|
46019
|
+
}
|
|
46020
|
+
return obj;
|
|
46021
|
+
};
|
|
46022
|
+
var clone = function (obj) {
|
|
46023
|
+
if (!isObject(obj)) {
|
|
46024
|
+
return obj;
|
|
46025
|
+
}
|
|
46026
|
+
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
46027
|
+
};
|
|
46028
|
+
|
|
46029
|
+
/* TODO batch *all* mutations
|
|
46030
|
+
* idea: freeze / thaw implementations for all types
|
|
46031
|
+
* lens constructor thaws, freeze delegates to type's freeze
|
|
46032
|
+
*/
|
|
46033
|
+
|
|
46034
|
+
// equivalents, without requiring it
|
|
46035
|
+
// find the implementation to use for a given object
|
|
46036
|
+
var dispatch = function (x) {
|
|
46037
|
+
if (Array.isArray(x)) {
|
|
46038
|
+
return arr;
|
|
46039
|
+
} else if (isObject(x)) {
|
|
46040
|
+
return obj;
|
|
46041
|
+
} else if (typeof x === "string") {
|
|
46042
|
+
return str;
|
|
46043
|
+
}
|
|
46044
|
+
};
|
|
46045
|
+
|
|
46046
|
+
// This is underscore with a different name
|
|
46047
|
+
var lens = function (obj) {
|
|
46048
|
+
if (obj instanceof lens) {
|
|
46049
|
+
return obj;
|
|
46050
|
+
}
|
|
46051
|
+
if (!(this instanceof lens)) {
|
|
46052
|
+
return new lens(obj);
|
|
46053
|
+
}
|
|
46054
|
+
var ops = dispatch(obj);
|
|
46055
|
+
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
46056
|
+
};
|
|
46057
|
+
lens.prototype.freeze = function () {
|
|
46058
|
+
var obj = this._wrapped;
|
|
46059
|
+
var ops = dispatch(obj);
|
|
46060
|
+
return ops.freeze ? ops.freeze(obj) : obj;
|
|
46061
|
+
};
|
|
46062
|
+
lens.prototype.zoom = function (lensArr) {
|
|
46063
|
+
if (this._zoomStack === undefined) {
|
|
46064
|
+
this._zoomStack = [];
|
|
46065
|
+
}
|
|
46066
|
+
this._zoomStack.push({
|
|
46067
|
+
zoom: lensArr,
|
|
46068
|
+
wrapped: this._wrapped
|
|
46069
|
+
});
|
|
46070
|
+
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
46071
|
+
return this;
|
|
46072
|
+
};
|
|
46073
|
+
lens.prototype.deZoom = function () {
|
|
46074
|
+
var frame = this._zoomStack.pop();
|
|
46075
|
+
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
46076
|
+
return this;
|
|
46077
|
+
};
|
|
46078
|
+
lens.prototype.get = function (lensArr) {
|
|
46079
|
+
var obj = this._wrapped;
|
|
46080
|
+
for (var i = 0; i < lensArr.length; i++) {
|
|
46081
|
+
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
46082
|
+
}
|
|
46083
|
+
return obj;
|
|
46084
|
+
};
|
|
46085
|
+
lens.prototype.mod = function (lensArr, f) {
|
|
46086
|
+
var obj = this._wrapped;
|
|
46087
|
+
var newObj = clone(obj);
|
|
46088
|
+
var ops = dispatch(obj);
|
|
46089
|
+
if (lensArr.length === 0) {
|
|
46090
|
+
this._wrapped = f(this._wrapped);
|
|
46091
|
+
} else if (lensArr.length === 1) {
|
|
46092
|
+
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
46093
|
+
} else {
|
|
46094
|
+
var monocle = lensArr[0];
|
|
46095
|
+
var shortLens = lensArr.slice(1);
|
|
46096
|
+
|
|
46097
|
+
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
46098
|
+
|
|
46099
|
+
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
46100
|
+
this._wrapped = newObj;
|
|
46101
|
+
}
|
|
46102
|
+
return this;
|
|
46103
|
+
};
|
|
46104
|
+
|
|
46105
|
+
// TODO - move to individual files
|
|
46106
|
+
lens.prototype.merge = function (lensArr, props) {
|
|
46107
|
+
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
46108
|
+
return merge(oldProps, props);
|
|
46109
|
+
}).freeze();
|
|
46110
|
+
return this;
|
|
46111
|
+
};
|
|
46112
|
+
|
|
46113
|
+
// Lens must have length >= 1 or there would be nothing to return
|
|
46114
|
+
lens.prototype.del = function (lensArr) {
|
|
46115
|
+
var obj = this._wrapped;
|
|
46116
|
+
var ops = dispatch(obj);
|
|
46117
|
+
if (lensArr.length === 1) {
|
|
46118
|
+
this._wrapped = ops.del(obj, lensArr[0]);
|
|
46119
|
+
} else {
|
|
46120
|
+
var monocle = lensArr[0];
|
|
46121
|
+
var shortLens = lensArr.slice(1);
|
|
46122
|
+
var newObj = clone(obj);
|
|
46123
|
+
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
46124
|
+
this._wrapped = newObj;
|
|
46125
|
+
}
|
|
46126
|
+
return this;
|
|
46127
|
+
};
|
|
46128
|
+
lens.prototype.set = function (lensArr, set) {
|
|
46129
|
+
return this.mod(lensArr, function () {
|
|
46130
|
+
return set;
|
|
46131
|
+
});
|
|
46132
|
+
};
|
|
46133
|
+
|
|
46134
|
+
// ARRAY FUNCTIONS
|
|
46135
|
+
|
|
46136
|
+
const arr = {
|
|
46137
|
+
get: function (arr, monocle) {
|
|
46138
|
+
return arr[monocle];
|
|
46139
|
+
},
|
|
46140
|
+
set: function (arr, monocle, val) {
|
|
46141
|
+
var newArr = arr.splice();
|
|
46142
|
+
newArr[monocle] = val;
|
|
46143
|
+
return newArr;
|
|
46144
|
+
},
|
|
46145
|
+
mod: function (arr, monocle, f) {
|
|
46146
|
+
var newArr = arr.slice();
|
|
46147
|
+
newArr[monocle] = f(arr[monocle]);
|
|
46148
|
+
return newArr;
|
|
46149
|
+
},
|
|
46150
|
+
del: function (arr, monocle) {
|
|
46151
|
+
var newArr = arr.slice();
|
|
46152
|
+
newArr.splice(monocle, 1);
|
|
46153
|
+
return newArr;
|
|
46154
|
+
}
|
|
46155
|
+
};
|
|
46156
|
+
|
|
46157
|
+
/*
|
|
46158
|
+
// Lens must point to a member of an array. We'll insert into that array.
|
|
46159
|
+
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
46160
|
+
var obj = this._wrapped;
|
|
46161
|
+
|
|
46162
|
+
var arrLens = lensArr.slice(0, -1);
|
|
46163
|
+
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
46164
|
+
|
|
46165
|
+
var arrIdx = lensArr[lensArr.length-1];
|
|
46166
|
+
arr.splice(arrIdx, 0, toInsert);
|
|
46167
|
+
return lens(obj).set(arrLens, arr);
|
|
46168
|
+
};
|
|
46169
|
+
|
|
46170
|
+
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
46171
|
+
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
46172
|
+
var newLens = lensArr.slice();
|
|
46173
|
+
newLens[newLens.length-1] += 1;
|
|
46174
|
+
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
46175
|
+
};
|
|
46176
|
+
*/
|
|
46177
|
+
|
|
46178
|
+
// OBJECT FUNCTIONS
|
|
46179
|
+
|
|
46180
|
+
const obj = {
|
|
46181
|
+
get: function (obj, monocle) {
|
|
46182
|
+
return obj[monocle];
|
|
46183
|
+
},
|
|
46184
|
+
set: function (obj, monocle, val) {
|
|
46185
|
+
var newObj = clone(obj);
|
|
46186
|
+
newObj[monocle] = val;
|
|
46187
|
+
return newObj;
|
|
46188
|
+
},
|
|
46189
|
+
mod: function (obj, monocle, f) {
|
|
46190
|
+
var newObj = clone(obj);
|
|
46191
|
+
newObj[monocle] = f(obj[monocle]);
|
|
46192
|
+
return newObj;
|
|
46193
|
+
},
|
|
46194
|
+
del: function (obj, monocle) {
|
|
46195
|
+
var newObj = clone(obj);
|
|
46196
|
+
delete newObj[monocle];
|
|
46197
|
+
return newObj;
|
|
46198
|
+
}
|
|
46199
|
+
};
|
|
46200
|
+
|
|
46201
|
+
// STRING FUNCTIONS
|
|
46202
|
+
|
|
46203
|
+
const str = {
|
|
46204
|
+
get: function (arr, monocle) {
|
|
46205
|
+
return arr[monocle];
|
|
46206
|
+
},
|
|
46207
|
+
set: function (arr, monocle, val) {
|
|
46208
|
+
var newArr = arr.splice();
|
|
46209
|
+
newArr[monocle] = val;
|
|
46210
|
+
return newArr;
|
|
46211
|
+
},
|
|
46212
|
+
mod: function (arr, monocle, f) {
|
|
46213
|
+
var newArr = arr.splice();
|
|
46214
|
+
newArr[monocle] = f(arr[monocle]);
|
|
46215
|
+
return newArr;
|
|
46216
|
+
},
|
|
46217
|
+
del: function (arr, monocle) {
|
|
46218
|
+
var newArr = arr.slice();
|
|
46219
|
+
newArr.splice(monocle);
|
|
46220
|
+
return newArr;
|
|
46221
|
+
}
|
|
46222
|
+
};
|
|
46223
|
+
|
|
46893
46224
|
// TODO(mdr)
|
|
46894
46225
|
// TODO(mdr)
|
|
46895
46226
|
// TODO(mdr)
|
|
@@ -47493,6 +46824,372 @@ function violatingWidgets(itemData) {
|
|
|
47493
46824
|
return ___default["default"].uniq(widgets);
|
|
47494
46825
|
}
|
|
47495
46826
|
|
|
46827
|
+
/* eslint-disable eqeqeq, @typescript-eslint/no-unused-vars */
|
|
46828
|
+
|
|
46829
|
+
/**
|
|
46830
|
+
* Format a floating point for display using the specified
|
|
46831
|
+
* number of significant figures and least significant decimal.
|
|
46832
|
+
* Scientific notation may used by this method if this
|
|
46833
|
+
* object is very small, very large, has many significant
|
|
46834
|
+
* figures, or the number of significant figures would be
|
|
46835
|
+
* ambiguous in the output if scientific notation were not
|
|
46836
|
+
* used.
|
|
46837
|
+
*
|
|
46838
|
+
* @param f A floating point number that should be displayed
|
|
46839
|
+
* @param sigFigs desired number of significant figures (integer).
|
|
46840
|
+
* @param sigDecs the least significant decimal place (integer).
|
|
46841
|
+
* @param scientific true iff scientific notation should always be used.
|
|
46842
|
+
* @return a string of this object formatted correctly.
|
|
46843
|
+
*/
|
|
46844
|
+
function displaySigFigs(f, sigFigs, sigDecs, scientific) {
|
|
46845
|
+
const s = "" + f;
|
|
46846
|
+
let order = parseOrder(s);
|
|
46847
|
+
let mantissa = parseMantissa(s);
|
|
46848
|
+
let positive = parseSign(s);
|
|
46849
|
+
let add;
|
|
46850
|
+
let decAdd;
|
|
46851
|
+
let sigAdd;
|
|
46852
|
+
let zeroScientific = false;
|
|
46853
|
+
if (f == 0 || mantissa == "" || mantissa == "0") {
|
|
46854
|
+
mantissa = "";
|
|
46855
|
+
for (let i = 0; i < sigFigs; i++) {
|
|
46856
|
+
mantissa += "0";
|
|
46857
|
+
}
|
|
46858
|
+
order = sigFigs + sigDecs;
|
|
46859
|
+
if (sigDecs < 0 && -sigDecs >= sigFigs) {
|
|
46860
|
+
zeroScientific = true;
|
|
46861
|
+
}
|
|
46862
|
+
} else {
|
|
46863
|
+
decAdd = order - mantissa.length - sigDecs;
|
|
46864
|
+
sigAdd = sigFigs - mantissa.length;
|
|
46865
|
+
add = Math.min(sigAdd, decAdd);
|
|
46866
|
+
if (add < 0) {
|
|
46867
|
+
let rounded = round(mantissa, -add);
|
|
46868
|
+
if (rounded.length > mantissa.length + add) {
|
|
46869
|
+
order++;
|
|
46870
|
+
if (decAdd > sigAdd) {
|
|
46871
|
+
rounded = round(rounded, 1);
|
|
46872
|
+
}
|
|
46873
|
+
}
|
|
46874
|
+
mantissa = rounded;
|
|
46875
|
+
} else if (add > 0) {
|
|
46876
|
+
for (let i = 0; i < add; i++) {
|
|
46877
|
+
mantissa += "0";
|
|
46878
|
+
}
|
|
46879
|
+
}
|
|
46880
|
+
if (mantissa == "" || mantissa == "0") {
|
|
46881
|
+
mantissa = "0";
|
|
46882
|
+
positive = true;
|
|
46883
|
+
order = 1 + sigDecs;
|
|
46884
|
+
if (order != 0) {
|
|
46885
|
+
zeroScientific = true;
|
|
46886
|
+
}
|
|
46887
|
+
}
|
|
46888
|
+
}
|
|
46889
|
+
const useScientific = scientific || mantissa.length > 20 || order > 4 || order < -2 || order - mantissa.length > 0 && trailingZeros(mantissa) > 0 || zeroScientific;
|
|
46890
|
+
let returnVal = "";
|
|
46891
|
+
if (!positive) {
|
|
46892
|
+
returnVal += "-";
|
|
46893
|
+
}
|
|
46894
|
+
if (useScientific) {
|
|
46895
|
+
returnVal += mantissa.charAt(0);
|
|
46896
|
+
if (mantissa.length > 1) {
|
|
46897
|
+
returnVal += "." + mantissa.substring(1, mantissa.length);
|
|
46898
|
+
}
|
|
46899
|
+
if (order - 1 != 0) {
|
|
46900
|
+
returnVal += " x 10^" + (order - 1);
|
|
46901
|
+
}
|
|
46902
|
+
} else {
|
|
46903
|
+
let wholePart = "";
|
|
46904
|
+
let fractPart = "";
|
|
46905
|
+
let needDot = true;
|
|
46906
|
+
if (order > 0) {
|
|
46907
|
+
if (mantissa.length > order) {
|
|
46908
|
+
wholePart = mantissa.substring(0, order);
|
|
46909
|
+
fractPart = mantissa.substring(order, mantissa.length);
|
|
46910
|
+
} else {
|
|
46911
|
+
wholePart = mantissa;
|
|
46912
|
+
needDot = trailingZeros(mantissa) != 0;
|
|
46913
|
+
for (let i = 0; i < order - mantissa.length; i++) {
|
|
46914
|
+
wholePart += "0";
|
|
46915
|
+
}
|
|
46916
|
+
}
|
|
46917
|
+
} else {
|
|
46918
|
+
for (let i = 0; i < -order; i++) {
|
|
46919
|
+
fractPart += "0";
|
|
46920
|
+
}
|
|
46921
|
+
fractPart += mantissa;
|
|
46922
|
+
}
|
|
46923
|
+
returnVal += (wholePart == "" ? "0" : wholePart) + (needDot ? "." : "") + fractPart;
|
|
46924
|
+
}
|
|
46925
|
+
return returnVal;
|
|
46926
|
+
}
|
|
46927
|
+
|
|
46928
|
+
/**
|
|
46929
|
+
* Count the significant trailing zeros on this object.
|
|
46930
|
+
*
|
|
46931
|
+
* @return the number of trailing zeros
|
|
46932
|
+
*/
|
|
46933
|
+
function trailingZeros(mantissa) {
|
|
46934
|
+
let zeros = 0;
|
|
46935
|
+
for (let i = mantissa.length - 1; i >= 0; i--) {
|
|
46936
|
+
const c = mantissa.charAt(i);
|
|
46937
|
+
if (c == "0") {
|
|
46938
|
+
zeros++;
|
|
46939
|
+
} else {
|
|
46940
|
+
return zeros;
|
|
46941
|
+
}
|
|
46942
|
+
}
|
|
46943
|
+
return zeros;
|
|
46944
|
+
}
|
|
46945
|
+
|
|
46946
|
+
/**
|
|
46947
|
+
* Parse a string representation of a floating point
|
|
46948
|
+
* and pull out the sign.
|
|
46949
|
+
*
|
|
46950
|
+
* @param s the string representation of a floating point.
|
|
46951
|
+
* @return true iff this is a positive number
|
|
46952
|
+
*/
|
|
46953
|
+
function parseSign(s) {
|
|
46954
|
+
let beginning = true;
|
|
46955
|
+
let seenDot = false;
|
|
46956
|
+
let seenSomething = false;
|
|
46957
|
+
let zeros = "";
|
|
46958
|
+
let all = "";
|
|
46959
|
+
let pos = true;
|
|
46960
|
+
for (let i = 0; i < s.length; i++) {
|
|
46961
|
+
const c = s.charAt(i);
|
|
46962
|
+
if (c >= "1" && c <= "9") {
|
|
46963
|
+
all += zeros + c;
|
|
46964
|
+
zeros = "";
|
|
46965
|
+
seenSomething = true;
|
|
46966
|
+
beginning = false;
|
|
46967
|
+
} else if (c == "0") {
|
|
46968
|
+
if (seenDot) {
|
|
46969
|
+
if (seenSomething) {
|
|
46970
|
+
all += zeros + c;
|
|
46971
|
+
zeros = "";
|
|
46972
|
+
}
|
|
46973
|
+
} else {
|
|
46974
|
+
if (seenSomething) {
|
|
46975
|
+
zeros += c;
|
|
46976
|
+
}
|
|
46977
|
+
}
|
|
46978
|
+
beginning = false;
|
|
46979
|
+
} else if (!seenDot && c == ".") {
|
|
46980
|
+
all += zeros;
|
|
46981
|
+
zeros = "";
|
|
46982
|
+
seenDot = true;
|
|
46983
|
+
beginning = false;
|
|
46984
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
46985
|
+
parseInt(s.substring(i + 1, s.length));
|
|
46986
|
+
i = s.length;
|
|
46987
|
+
} else if (beginning && (c == "+" || c == "-")) {
|
|
46988
|
+
if (c == "-") {
|
|
46989
|
+
pos = !pos;
|
|
46990
|
+
}
|
|
46991
|
+
}
|
|
46992
|
+
}
|
|
46993
|
+
if (all == "") {
|
|
46994
|
+
return true;
|
|
46995
|
+
}
|
|
46996
|
+
return pos;
|
|
46997
|
+
}
|
|
46998
|
+
|
|
46999
|
+
/**
|
|
47000
|
+
* Parse a string representation of a floating point
|
|
47001
|
+
* and pull out the mantissa.
|
|
47002
|
+
*
|
|
47003
|
+
* @param s the string representation of a floating point.
|
|
47004
|
+
* @return the mantissa of this number.
|
|
47005
|
+
*/
|
|
47006
|
+
function parseMantissa(s) {
|
|
47007
|
+
let seenDot = false;
|
|
47008
|
+
let seenSomething = false;
|
|
47009
|
+
let zeros = "";
|
|
47010
|
+
let leadZeros = "";
|
|
47011
|
+
let all = "";
|
|
47012
|
+
for (let i = 0; i < s.length; i++) {
|
|
47013
|
+
const c = s.charAt(i);
|
|
47014
|
+
if (c >= "1" && c <= "9") {
|
|
47015
|
+
all += zeros + c;
|
|
47016
|
+
zeros = "";
|
|
47017
|
+
seenSomething = true;
|
|
47018
|
+
} else if (c == "0") {
|
|
47019
|
+
if (seenDot) {
|
|
47020
|
+
if (seenSomething) {
|
|
47021
|
+
all += zeros + c;
|
|
47022
|
+
zeros = "";
|
|
47023
|
+
} else {
|
|
47024
|
+
leadZeros += c;
|
|
47025
|
+
}
|
|
47026
|
+
} else {
|
|
47027
|
+
if (seenSomething) {
|
|
47028
|
+
leadZeros += c;
|
|
47029
|
+
zeros += c;
|
|
47030
|
+
} else {
|
|
47031
|
+
leadZeros += c;
|
|
47032
|
+
}
|
|
47033
|
+
}
|
|
47034
|
+
} else if (!seenDot && c == ".") {
|
|
47035
|
+
all += zeros;
|
|
47036
|
+
zeros = "";
|
|
47037
|
+
seenDot = true;
|
|
47038
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
47039
|
+
parseInt(s.substring(i + 1, s.length));
|
|
47040
|
+
i = s.length;
|
|
47041
|
+
} else ;
|
|
47042
|
+
}
|
|
47043
|
+
if (all == "") {
|
|
47044
|
+
return leadZeros;
|
|
47045
|
+
}
|
|
47046
|
+
return all;
|
|
47047
|
+
}
|
|
47048
|
+
|
|
47049
|
+
/**
|
|
47050
|
+
* Parse a string representation of a floating point
|
|
47051
|
+
* and pull out the exponent.
|
|
47052
|
+
*
|
|
47053
|
+
* @param s the string representation of a floating point.
|
|
47054
|
+
* @return (integer) the number after the e.
|
|
47055
|
+
*/
|
|
47056
|
+
function parseOrder(s) {
|
|
47057
|
+
let seenDot = false;
|
|
47058
|
+
let seenSomething = false;
|
|
47059
|
+
let zeros = "";
|
|
47060
|
+
let all = "";
|
|
47061
|
+
let decPlaces = 0;
|
|
47062
|
+
let totalDecs = 0;
|
|
47063
|
+
for (let i = 0; i < s.length; i++) {
|
|
47064
|
+
const c = s.charAt(i);
|
|
47065
|
+
if (c >= "1" && c <= "9") {
|
|
47066
|
+
all += zeros + c;
|
|
47067
|
+
zeros = "";
|
|
47068
|
+
seenSomething = true;
|
|
47069
|
+
if (!seenDot) {
|
|
47070
|
+
totalDecs++;
|
|
47071
|
+
decPlaces++;
|
|
47072
|
+
}
|
|
47073
|
+
} else if (c == "0") {
|
|
47074
|
+
if (seenDot) {
|
|
47075
|
+
if (seenSomething) {
|
|
47076
|
+
all += zeros + c;
|
|
47077
|
+
zeros = "";
|
|
47078
|
+
} else {
|
|
47079
|
+
decPlaces--;
|
|
47080
|
+
}
|
|
47081
|
+
} else {
|
|
47082
|
+
totalDecs++;
|
|
47083
|
+
if (seenSomething) {
|
|
47084
|
+
decPlaces++;
|
|
47085
|
+
zeros += c;
|
|
47086
|
+
}
|
|
47087
|
+
}
|
|
47088
|
+
} else if (!seenDot && c == ".") {
|
|
47089
|
+
all += zeros;
|
|
47090
|
+
zeros = "";
|
|
47091
|
+
seenDot = true;
|
|
47092
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
47093
|
+
const raised = parseInt(s.substring(i + 1, s.length));
|
|
47094
|
+
decPlaces += raised;
|
|
47095
|
+
totalDecs += raised;
|
|
47096
|
+
i = s.length;
|
|
47097
|
+
} else ;
|
|
47098
|
+
}
|
|
47099
|
+
if (all == "") {
|
|
47100
|
+
return totalDecs;
|
|
47101
|
+
}
|
|
47102
|
+
return decPlaces;
|
|
47103
|
+
}
|
|
47104
|
+
|
|
47105
|
+
/**
|
|
47106
|
+
* Remove the specified number of digits from string by
|
|
47107
|
+
* rounding. Proper rounding rules for scientific purposes
|
|
47108
|
+
* are followed.
|
|
47109
|
+
* This method may cause an extra significant figure
|
|
47110
|
+
* to be added to the number. For example, if 999999
|
|
47111
|
+
* were rounded, A one would carry over and become
|
|
47112
|
+
* a significant figure. Those who call this method
|
|
47113
|
+
* should check for this and call round again if needed.
|
|
47114
|
+
*
|
|
47115
|
+
* @param mantissa A string representing an whole number of arbitrary length.
|
|
47116
|
+
* @param digits A number of digits to remove
|
|
47117
|
+
* @return A string represted the rounded version of mantissa
|
|
47118
|
+
*/
|
|
47119
|
+
function round(mantissa, digits) {
|
|
47120
|
+
const last = mantissa.length - digits - 1;
|
|
47121
|
+
if (last < 0) {
|
|
47122
|
+
return "";
|
|
47123
|
+
}
|
|
47124
|
+
if (last >= mantissa.length - 1) {
|
|
47125
|
+
return mantissa;
|
|
47126
|
+
}
|
|
47127
|
+
const nextToLast = mantissa.charAt(last + 1);
|
|
47128
|
+
const lastChar = mantissa.charAt(last);
|
|
47129
|
+
let roundUp = false;
|
|
47130
|
+
if (nextToLast > "5") {
|
|
47131
|
+
roundUp = true;
|
|
47132
|
+
} else if (nextToLast == "5") {
|
|
47133
|
+
for (let j = last + 2; j < mantissa.length; j++) {
|
|
47134
|
+
if (mantissa.charAt(j) != "0") {
|
|
47135
|
+
roundUp = true;
|
|
47136
|
+
}
|
|
47137
|
+
}
|
|
47138
|
+
// @ts-expect-error - TS2362 - The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
|
|
47139
|
+
if (lastChar % 2 == 1) {
|
|
47140
|
+
roundUp = true;
|
|
47141
|
+
}
|
|
47142
|
+
}
|
|
47143
|
+
let result = "";
|
|
47144
|
+
for (let i = last; i >= 0; i--) {
|
|
47145
|
+
const c = mantissa.charAt(i);
|
|
47146
|
+
if (roundUp) {
|
|
47147
|
+
let nextChar;
|
|
47148
|
+
if (c == "9") {
|
|
47149
|
+
nextChar = "0";
|
|
47150
|
+
} else {
|
|
47151
|
+
switch (c) {
|
|
47152
|
+
case "0":
|
|
47153
|
+
nextChar = "1";
|
|
47154
|
+
break;
|
|
47155
|
+
case "1":
|
|
47156
|
+
nextChar = "2";
|
|
47157
|
+
break;
|
|
47158
|
+
case "2":
|
|
47159
|
+
nextChar = "3";
|
|
47160
|
+
break;
|
|
47161
|
+
case "3":
|
|
47162
|
+
nextChar = "4";
|
|
47163
|
+
break;
|
|
47164
|
+
case "4":
|
|
47165
|
+
nextChar = "5";
|
|
47166
|
+
break;
|
|
47167
|
+
case "5":
|
|
47168
|
+
nextChar = "6";
|
|
47169
|
+
break;
|
|
47170
|
+
case "6":
|
|
47171
|
+
nextChar = "7";
|
|
47172
|
+
break;
|
|
47173
|
+
case "7":
|
|
47174
|
+
nextChar = "8";
|
|
47175
|
+
break;
|
|
47176
|
+
case "8":
|
|
47177
|
+
nextChar = "9";
|
|
47178
|
+
break;
|
|
47179
|
+
}
|
|
47180
|
+
roundUp = false;
|
|
47181
|
+
}
|
|
47182
|
+
result = nextChar + result;
|
|
47183
|
+
} else {
|
|
47184
|
+
result = c + result;
|
|
47185
|
+
}
|
|
47186
|
+
}
|
|
47187
|
+
if (roundUp) {
|
|
47188
|
+
result = "1" + result;
|
|
47189
|
+
}
|
|
47190
|
+
return result;
|
|
47191
|
+
}
|
|
47192
|
+
|
|
47496
47193
|
/**
|
|
47497
47194
|
* Some tests require some or all of the widgets and editors to be registered
|
|
47498
47195
|
* in order for them to work. Requiring this file will register all of the
|
|
@@ -48214,9 +47911,6 @@ function generateTestInteractiveGraphWidget() {
|
|
|
48214
47911
|
markings: "graph",
|
|
48215
47912
|
labels: ["x", "y"],
|
|
48216
47913
|
showProtractor: false,
|
|
48217
|
-
showRuler: false,
|
|
48218
|
-
rulerLabel: "mm",
|
|
48219
|
-
rulerTicks: 2,
|
|
48220
47914
|
range: [[-10, 10], [-10, 10]],
|
|
48221
47915
|
graph: {
|
|
48222
47916
|
type: "angle"
|
|
@@ -48328,7 +48022,6 @@ const widgetNameToEnum = {
|
|
|
48328
48022
|
simulator: "SIMULATOR",
|
|
48329
48023
|
sorter: "SORTER",
|
|
48330
48024
|
table: "TABLE",
|
|
48331
|
-
"unit-input": "UNIT",
|
|
48332
48025
|
video: "VIDEO"
|
|
48333
48026
|
};
|
|
48334
48027
|
function convertWidgetNameToEnum(name) {
|
|
@@ -48410,6 +48103,8 @@ exports.getAnswerFromUserInput = getAnswerFromUserInput;
|
|
|
48410
48103
|
exports.getAnswersFromWidgets = getAnswersFromWidgets;
|
|
48411
48104
|
exports.getCorrectAnswerForWidgetId = getCorrectAnswerForWidgetId;
|
|
48412
48105
|
exports.getLineCoords = getLineCoords;
|
|
48106
|
+
exports.getLinearSystemCoords = getLinearSystemCoords;
|
|
48107
|
+
exports.getSegmentCoords = getSegmentCoords;
|
|
48413
48108
|
exports.getValidWidgetIds = getValidWidgetIds;
|
|
48414
48109
|
exports.getWidgetFromWidgetMap = getWidgetFromWidgetMap;
|
|
48415
48110
|
exports.getWidgetIdsFromContent = getWidgetIdsFromContent;
|