@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/es/index.js
CHANGED
|
@@ -501,6 +501,7 @@ class InnerMathInput extends React.Component {
|
|
|
501
501
|
}), /*#__PURE__*/React.createElement(Popover, {
|
|
502
502
|
opened: this.state.keypadOpen,
|
|
503
503
|
onClose: () => this.closeKeypad(),
|
|
504
|
+
portal: false,
|
|
504
505
|
dismissEnabled: true,
|
|
505
506
|
content: () => {
|
|
506
507
|
var _this$props$keypadBut, _this$props;
|
|
@@ -730,7 +731,7 @@ const denylist = [
|
|
|
730
731
|
// (technically the renderer still adds them)
|
|
731
732
|
"key", "ref",
|
|
732
733
|
// added by src/renderer.jsx
|
|
733
|
-
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets",
|
|
734
|
+
"containerSizeClass", "widgetId", "onChange", "problemNum", "apiOptions", "questionCompleted", "findWidgets", "hintMode",
|
|
734
735
|
// added by src/editor.jsx, for widgets removing themselves
|
|
735
736
|
// this is soooo not the right place for this, but alas.
|
|
736
737
|
"onRemove",
|
|
@@ -19014,6 +19015,7 @@ const replaceDeprecatedWidgets = () => {
|
|
|
19014
19015
|
replaceWidget("reaction-diagram", "deprecated-standin");
|
|
19015
19016
|
replaceWidget("sequence", "deprecated-standin");
|
|
19016
19017
|
replaceWidget("simulator", "deprecated-standin");
|
|
19018
|
+
replaceWidget("unit-input", "deprecated-standin");
|
|
19017
19019
|
};
|
|
19018
19020
|
const registerEditors = editorsToRegister => {
|
|
19019
19021
|
editorsToRegister.forEach(editor => {
|
|
@@ -19047,6 +19049,7 @@ const replaceDeprecatedEditors = () => {
|
|
|
19047
19049
|
replaceEditor("reaction-diagram", "deprecated-standin");
|
|
19048
19050
|
replaceEditor("sequence", "deprecated-standin");
|
|
19049
19051
|
replaceEditor("simulator", "deprecated-standin");
|
|
19052
|
+
replaceEditor("unit-input", "deprecated-standin");
|
|
19050
19053
|
};
|
|
19051
19054
|
const getWidget = name => {
|
|
19052
19055
|
var _widgets$name;
|
|
@@ -19731,6 +19734,7 @@ class Renderer extends React.Component {
|
|
|
19731
19734
|
onBlur: _.partial(this._onWidgetBlur, id),
|
|
19732
19735
|
findWidgets: this.findWidgets,
|
|
19733
19736
|
reviewModeRubric: reviewModeRubric,
|
|
19737
|
+
hintMode: this.props.hintMode,
|
|
19734
19738
|
onChange: (newProps, cb, silent = false) => {
|
|
19735
19739
|
this._setWidgetProps(id, newProps, cb, silent);
|
|
19736
19740
|
},
|
|
@@ -20930,6 +20934,7 @@ Renderer.defaultProps = {
|
|
|
20930
20934
|
findExternalWidgets: () => [],
|
|
20931
20935
|
alwaysUpdate: false,
|
|
20932
20936
|
reviewMode: false,
|
|
20937
|
+
hintMode: false,
|
|
20933
20938
|
serializedState: null,
|
|
20934
20939
|
onSerializedStateUpdated: () => {},
|
|
20935
20940
|
linterContext: PerseusLinter.linterContextDefault
|
|
@@ -28298,7 +28303,8 @@ const defaultGraphConfig = {
|
|
|
28298
28303
|
graphDimensionsInPixels: [1, 1],
|
|
28299
28304
|
width: 0,
|
|
28300
28305
|
height: 0,
|
|
28301
|
-
labels: []
|
|
28306
|
+
labels: [],
|
|
28307
|
+
hintMode: false
|
|
28302
28308
|
};
|
|
28303
28309
|
const GraphConfigContext = /*#__PURE__*/createContext(defaultGraphConfig);
|
|
28304
28310
|
function useGraphConfig() {
|
|
@@ -29766,8 +29772,6 @@ const ItemExtras = [
|
|
|
29766
29772
|
|
|
29767
29773
|
// prettier-ignore
|
|
29768
29774
|
|
|
29769
|
-
// prettier-ignore
|
|
29770
|
-
|
|
29771
29775
|
//prettier-ignore
|
|
29772
29776
|
|
|
29773
29777
|
// A background image applied to various widgets.
|
|
@@ -30292,6 +30296,16 @@ function useDraggable(args) {
|
|
|
30292
30296
|
const isKeyboard = type.includes("key");
|
|
30293
30297
|
if (isKeyboard) {
|
|
30294
30298
|
event == null || event.preventDefault();
|
|
30299
|
+
|
|
30300
|
+
// When a key is held down, we see multiple "keydown" events,
|
|
30301
|
+
// followed by a single "keyup" event.
|
|
30302
|
+
// For a single keypress, we only see a "keydown" event, no
|
|
30303
|
+
// "keyup".
|
|
30304
|
+
// We never want to process the keyup event as an intent to
|
|
30305
|
+
// move so we bail on further processing here.
|
|
30306
|
+
if (type === "keyup") {
|
|
30307
|
+
return;
|
|
30308
|
+
}
|
|
30295
30309
|
const {
|
|
30296
30310
|
direction: yDownDirection,
|
|
30297
30311
|
altKey,
|
|
@@ -30392,7 +30406,8 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30392
30406
|
const {
|
|
30393
30407
|
range,
|
|
30394
30408
|
markings,
|
|
30395
|
-
showTooltips
|
|
30409
|
+
showTooltips,
|
|
30410
|
+
hintMode
|
|
30396
30411
|
} = useGraphConfig();
|
|
30397
30412
|
const {
|
|
30398
30413
|
point,
|
|
@@ -30434,7 +30449,7 @@ const MovablePointView = /*#__PURE__*/forwardRef((props, hitboxRef) => {
|
|
|
30434
30449
|
cursor
|
|
30435
30450
|
},
|
|
30436
30451
|
"data-testid": "movable-point",
|
|
30437
|
-
tabIndex: tabIndex(focusBehavior)
|
|
30452
|
+
tabIndex: hintMode ? -1 : tabIndex(focusBehavior)
|
|
30438
30453
|
}, /*#__PURE__*/React.createElement("circle", {
|
|
30439
30454
|
className: "movable-point-hitbox",
|
|
30440
30455
|
r: hitboxSizePx / 2,
|
|
@@ -30522,7 +30537,8 @@ const MovableLine = props => {
|
|
|
30522
30537
|
};
|
|
30523
30538
|
function useControlPoint(point, color, onMovePoint) {
|
|
30524
30539
|
const {
|
|
30525
|
-
snapStep
|
|
30540
|
+
snapStep,
|
|
30541
|
+
hintMode
|
|
30526
30542
|
} = useGraphConfig();
|
|
30527
30543
|
const [focused, setFocused] = useState(false);
|
|
30528
30544
|
const keyboardHandleRef = useRef(null);
|
|
@@ -30544,7 +30560,7 @@ function useControlPoint(point, color, onMovePoint) {
|
|
|
30544
30560
|
const focusableHandle = /*#__PURE__*/React.createElement("g", {
|
|
30545
30561
|
"data-testid": "movable-point__focusable-handle",
|
|
30546
30562
|
className: "movable-point__focusable-handle",
|
|
30547
|
-
tabIndex: 0,
|
|
30563
|
+
tabIndex: hintMode ? -1 : 0,
|
|
30548
30564
|
ref: keyboardHandleRef,
|
|
30549
30565
|
onFocus: () => setFocused(true),
|
|
30550
30566
|
onBlur: () => setFocused(false)
|
|
@@ -30577,7 +30593,8 @@ const Line$1 = props => {
|
|
|
30577
30593
|
const {
|
|
30578
30594
|
range,
|
|
30579
30595
|
graphDimensionsInPixels,
|
|
30580
|
-
snapStep
|
|
30596
|
+
snapStep,
|
|
30597
|
+
hintMode
|
|
30581
30598
|
} = useGraphConfig();
|
|
30582
30599
|
let startExtend = undefined;
|
|
30583
30600
|
let endExtend = undefined;
|
|
@@ -30599,7 +30616,7 @@ const Line$1 = props => {
|
|
|
30599
30616
|
});
|
|
30600
30617
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("g", {
|
|
30601
30618
|
ref: line,
|
|
30602
|
-
tabIndex: 0,
|
|
30619
|
+
tabIndex: hintMode ? -1 : 0,
|
|
30603
30620
|
className: "movable-line",
|
|
30604
30621
|
"data-testid": "movable-line",
|
|
30605
30622
|
style: {
|
|
@@ -31110,6 +31127,9 @@ const PolygonGraph = props => {
|
|
|
31110
31127
|
snapStep,
|
|
31111
31128
|
snapTo
|
|
31112
31129
|
} = props.graphState;
|
|
31130
|
+
const {
|
|
31131
|
+
hintMode
|
|
31132
|
+
} = useGraphConfig();
|
|
31113
31133
|
|
|
31114
31134
|
// TODO(benchristel): can the default set of points be removed here? I don't
|
|
31115
31135
|
// think coords can be null.
|
|
@@ -31129,12 +31149,16 @@ const PolygonGraph = props => {
|
|
|
31129
31149
|
constrain: p => ["angles", "sides"].includes(snapToValue) ? p : snap(snapStep, p)
|
|
31130
31150
|
});
|
|
31131
31151
|
const active = hovered || focused || dragging;
|
|
31152
|
+
const lastMoveTime = React.useRef(0);
|
|
31132
31153
|
const lines = getLines(points);
|
|
31133
31154
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Polygon, {
|
|
31134
31155
|
points: [...points],
|
|
31135
31156
|
color: "var(--movable-line-stroke-color)",
|
|
31136
31157
|
svgPolygonProps: {
|
|
31137
|
-
strokeWidth: active ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)"
|
|
31158
|
+
strokeWidth: active ? "var(--movable-line-stroke-weight-active)" : "var(--movable-line-stroke-weight)",
|
|
31159
|
+
style: {
|
|
31160
|
+
fill: "transparent"
|
|
31161
|
+
}
|
|
31138
31162
|
}
|
|
31139
31163
|
}), points.map((point, i) => {
|
|
31140
31164
|
const pt1 = points.at(i - 1);
|
|
@@ -31165,10 +31189,11 @@ const PolygonGraph = props => {
|
|
|
31165
31189
|
color: "transparent",
|
|
31166
31190
|
svgPolygonProps: {
|
|
31167
31191
|
ref,
|
|
31168
|
-
tabIndex: 0,
|
|
31192
|
+
tabIndex: hintMode ? -1 : 0,
|
|
31169
31193
|
strokeWidth: TARGET_SIZE,
|
|
31170
31194
|
style: {
|
|
31171
|
-
cursor: dragging ? "grabbing" : "grab"
|
|
31195
|
+
cursor: dragging ? "grabbing" : "grab",
|
|
31196
|
+
fill: hovered ? "var(--mafs-blue)" : "transparent"
|
|
31172
31197
|
},
|
|
31173
31198
|
onFocus: () => setFocused(true),
|
|
31174
31199
|
onBlur: () => setFocused(false),
|
|
@@ -31180,7 +31205,15 @@ const PolygonGraph = props => {
|
|
|
31180
31205
|
key: "point-" + i,
|
|
31181
31206
|
snapTo: snapTo,
|
|
31182
31207
|
point: point,
|
|
31183
|
-
onMove: destination =>
|
|
31208
|
+
onMove: destination => {
|
|
31209
|
+
const now = Date.now();
|
|
31210
|
+
const targetFPS = 40;
|
|
31211
|
+
const moveThresholdTime = 1000 / targetFPS;
|
|
31212
|
+
if (now - lastMoveTime.current > moveThresholdTime) {
|
|
31213
|
+
dispatch(actions.polygon.movePoint(i, destination));
|
|
31214
|
+
lastMoveTime.current = now;
|
|
31215
|
+
}
|
|
31216
|
+
}
|
|
31184
31217
|
})));
|
|
31185
31218
|
};
|
|
31186
31219
|
function getLines(points) {
|
|
@@ -31289,7 +31322,8 @@ function MovableCircle(props) {
|
|
|
31289
31322
|
onMove
|
|
31290
31323
|
} = props;
|
|
31291
31324
|
const {
|
|
31292
|
-
snapStep
|
|
31325
|
+
snapStep,
|
|
31326
|
+
hintMode
|
|
31293
31327
|
} = useGraphConfig();
|
|
31294
31328
|
const draggableRef = useRef(null);
|
|
31295
31329
|
const {
|
|
@@ -31304,7 +31338,7 @@ function MovableCircle(props) {
|
|
|
31304
31338
|
const [radiiPx] = useTransformDimensionsToPixels([radius, radius]);
|
|
31305
31339
|
return /*#__PURE__*/React.createElement("g", {
|
|
31306
31340
|
ref: draggableRef,
|
|
31307
|
-
tabIndex: 0,
|
|
31341
|
+
tabIndex: hintMode ? -1 : 0,
|
|
31308
31342
|
className: `movable-circle ${dragging ? "movable-circle--dragging" : ""}`
|
|
31309
31343
|
}, /*#__PURE__*/React.createElement("ellipse", {
|
|
31310
31344
|
className: "focus-ring",
|
|
@@ -31707,7 +31741,8 @@ const MafsGraph = props => {
|
|
|
31707
31741
|
const {
|
|
31708
31742
|
state,
|
|
31709
31743
|
dispatch,
|
|
31710
|
-
labels
|
|
31744
|
+
labels,
|
|
31745
|
+
hintMode
|
|
31711
31746
|
} = props;
|
|
31712
31747
|
const [width, height] = props.box;
|
|
31713
31748
|
const tickStep = props.step;
|
|
@@ -31722,7 +31757,8 @@ const MafsGraph = props => {
|
|
|
31722
31757
|
graphDimensionsInPixels: props.box,
|
|
31723
31758
|
width,
|
|
31724
31759
|
height,
|
|
31725
|
-
labels
|
|
31760
|
+
labels,
|
|
31761
|
+
hintMode
|
|
31726
31762
|
}
|
|
31727
31763
|
}, /*#__PURE__*/React.createElement(View, {
|
|
31728
31764
|
className: "mafs-graph",
|
|
@@ -31733,7 +31769,8 @@ const MafsGraph = props => {
|
|
|
31733
31769
|
padding: "25px 25px 0 0",
|
|
31734
31770
|
boxSizing: "content-box",
|
|
31735
31771
|
marginLeft: "20px",
|
|
31736
|
-
marginBottom: "20px"
|
|
31772
|
+
marginBottom: "20px",
|
|
31773
|
+
pointerEvents: hintMode ? "none" : "auto"
|
|
31737
31774
|
}
|
|
31738
31775
|
}, /*#__PURE__*/React.createElement(LegacyGrid, {
|
|
31739
31776
|
box: props.box,
|
|
@@ -31764,7 +31801,7 @@ const MafsGraph = props => {
|
|
|
31764
31801
|
}), props.lockedFigures && /*#__PURE__*/React.createElement(GraphLockedLayer, {
|
|
31765
31802
|
lockedFigures: props.lockedFigures,
|
|
31766
31803
|
range: state.range
|
|
31767
|
-
}),
|
|
31804
|
+
}), props.showProtractor && /*#__PURE__*/React.createElement(Protractor, null), renderGraph({
|
|
31768
31805
|
state,
|
|
31769
31806
|
dispatch
|
|
31770
31807
|
})))));
|
|
@@ -32793,7 +32830,6 @@ function mafsStateToInteractiveGraph(state) {
|
|
|
32793
32830
|
return _extends({}, state);
|
|
32794
32831
|
}
|
|
32795
32832
|
const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
32796
|
-
var _graph$startCoords;
|
|
32797
32833
|
const {
|
|
32798
32834
|
onChange,
|
|
32799
32835
|
graph
|
|
@@ -32828,7 +32864,6 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32828
32864
|
const snapTo = graph.type === "polygon" ? graph.snapTo : null;
|
|
32829
32865
|
const showAngles = graph.type === "polygon" ? graph.showAngles : null;
|
|
32830
32866
|
const showSides = graph.type === "polygon" ? graph.showSides : null;
|
|
32831
|
-
const startCoords = (_graph$startCoords = graph.startCoords) != null ? _graph$startCoords : null;
|
|
32832
32867
|
const originalPropsRef = useRef(props);
|
|
32833
32868
|
const latestPropsRef = useLatestRef(props);
|
|
32834
32869
|
useEffect(() => {
|
|
@@ -32839,7 +32874,7 @@ const StatefulMafsGraph = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
32839
32874
|
if (latestPropsRef.current !== originalPropsRef.current) {
|
|
32840
32875
|
dispatch(reinitialize(latestPropsRef.current));
|
|
32841
32876
|
}
|
|
32842
|
-
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides,
|
|
32877
|
+
}, [graph.type, numSegments, numSides, snapTo, showAngles, showSides, latestPropsRef, graph.startCoords]);
|
|
32843
32878
|
return /*#__PURE__*/React.createElement(MafsGraph, _extends({}, props, {
|
|
32844
32879
|
state: state,
|
|
32845
32880
|
dispatch: dispatch
|
|
@@ -34100,9 +34135,6 @@ class LegacyInteractiveGraph extends React.Component {
|
|
|
34100
34135
|
markings: this.props.markings,
|
|
34101
34136
|
backgroundImage: this.props.backgroundImage,
|
|
34102
34137
|
showProtractor: this.props.showProtractor,
|
|
34103
|
-
showRuler: this.props.showRuler,
|
|
34104
|
-
rulerLabel: this.props.rulerLabel,
|
|
34105
|
-
rulerTicks: this.props.rulerTicks,
|
|
34106
34138
|
onMouseDown: onMouseDown,
|
|
34107
34139
|
onGraphieUpdated: this.setGraphie,
|
|
34108
34140
|
setDrawingAreaAvailable: this.props.apiOptions.setDrawingAreaAvailable,
|
|
@@ -34119,9 +34151,6 @@ LegacyInteractiveGraph.defaultProps = {
|
|
|
34119
34151
|
markings: "graph",
|
|
34120
34152
|
showTooltips: false,
|
|
34121
34153
|
showProtractor: false,
|
|
34122
|
-
showRuler: false,
|
|
34123
|
-
rulerLabel: "",
|
|
34124
|
-
rulerTicks: 10,
|
|
34125
34154
|
graph: {
|
|
34126
34155
|
type: "linear"
|
|
34127
34156
|
}
|
|
@@ -34159,7 +34188,8 @@ class InteractiveGraph extends React.Component {
|
|
|
34159
34188
|
gridStep: gridStep,
|
|
34160
34189
|
snapStep: snapStep,
|
|
34161
34190
|
box: box,
|
|
34162
|
-
showTooltips: !!this.props.showTooltips
|
|
34191
|
+
showTooltips: !!this.props.showTooltips,
|
|
34192
|
+
hintMode: this.props.hintMode
|
|
34163
34193
|
}));
|
|
34164
34194
|
}
|
|
34165
34195
|
return /*#__PURE__*/React.createElement(LegacyInteractiveGraph, _extends({
|
|
@@ -34719,9 +34749,6 @@ InteractiveGraph.defaultProps = {
|
|
|
34719
34749
|
markings: "graph",
|
|
34720
34750
|
showTooltips: false,
|
|
34721
34751
|
showProtractor: false,
|
|
34722
|
-
showRuler: false,
|
|
34723
|
-
rulerLabel: "",
|
|
34724
|
-
rulerTicks: 10,
|
|
34725
34752
|
graph: {
|
|
34726
34753
|
type: "linear"
|
|
34727
34754
|
}
|
|
@@ -43850,914 +43877,6 @@ var Table$1 = {
|
|
|
43850
43877
|
isLintable: true
|
|
43851
43878
|
};
|
|
43852
43879
|
|
|
43853
|
-
var isObject = function isObject(obj) {
|
|
43854
|
-
return obj === Object(obj);
|
|
43855
|
-
};
|
|
43856
|
-
var merge = function merge() {
|
|
43857
|
-
var obj = {};
|
|
43858
|
-
for (var i = 0; i < arguments.length; i++) {
|
|
43859
|
-
var source = arguments[i];
|
|
43860
|
-
if (source) {
|
|
43861
|
-
for (var prop in source) {
|
|
43862
|
-
obj[prop] = source[prop];
|
|
43863
|
-
}
|
|
43864
|
-
}
|
|
43865
|
-
}
|
|
43866
|
-
return obj;
|
|
43867
|
-
};
|
|
43868
|
-
var clone = function clone(obj) {
|
|
43869
|
-
if (!isObject(obj)) {
|
|
43870
|
-
return obj;
|
|
43871
|
-
}
|
|
43872
|
-
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
43873
|
-
};
|
|
43874
|
-
|
|
43875
|
-
/* TODO batch *all* mutations
|
|
43876
|
-
* idea: freeze / thaw implementations for all types
|
|
43877
|
-
* lens constructor thaws, freeze delegates to type's freeze
|
|
43878
|
-
*/
|
|
43879
|
-
|
|
43880
|
-
// equivalents, without requiring it
|
|
43881
|
-
// find the implementation to use for a given object
|
|
43882
|
-
var dispatch = function dispatch(x) {
|
|
43883
|
-
if (Array.isArray(x)) {
|
|
43884
|
-
return arr;
|
|
43885
|
-
} else if (isObject(x)) {
|
|
43886
|
-
return obj;
|
|
43887
|
-
} else if (typeof x === "string") {
|
|
43888
|
-
return str;
|
|
43889
|
-
}
|
|
43890
|
-
};
|
|
43891
|
-
|
|
43892
|
-
// This is underscore with a different name
|
|
43893
|
-
var lens = function lens(obj) {
|
|
43894
|
-
if (obj instanceof lens) {
|
|
43895
|
-
return obj;
|
|
43896
|
-
}
|
|
43897
|
-
if (!(this instanceof lens)) {
|
|
43898
|
-
return new lens(obj);
|
|
43899
|
-
}
|
|
43900
|
-
var ops = dispatch(obj);
|
|
43901
|
-
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
43902
|
-
};
|
|
43903
|
-
lens.prototype.freeze = function () {
|
|
43904
|
-
var obj = this._wrapped;
|
|
43905
|
-
var ops = dispatch(obj);
|
|
43906
|
-
return ops.freeze ? ops.freeze(obj) : obj;
|
|
43907
|
-
};
|
|
43908
|
-
lens.prototype.zoom = function (lensArr) {
|
|
43909
|
-
if (this._zoomStack === undefined) {
|
|
43910
|
-
this._zoomStack = [];
|
|
43911
|
-
}
|
|
43912
|
-
this._zoomStack.push({
|
|
43913
|
-
zoom: lensArr,
|
|
43914
|
-
wrapped: this._wrapped
|
|
43915
|
-
});
|
|
43916
|
-
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
43917
|
-
return this;
|
|
43918
|
-
};
|
|
43919
|
-
lens.prototype.deZoom = function () {
|
|
43920
|
-
var frame = this._zoomStack.pop();
|
|
43921
|
-
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
43922
|
-
return this;
|
|
43923
|
-
};
|
|
43924
|
-
lens.prototype.get = function (lensArr) {
|
|
43925
|
-
var obj = this._wrapped;
|
|
43926
|
-
for (var i = 0; i < lensArr.length; i++) {
|
|
43927
|
-
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
43928
|
-
}
|
|
43929
|
-
return obj;
|
|
43930
|
-
};
|
|
43931
|
-
lens.prototype.mod = function (lensArr, f) {
|
|
43932
|
-
var obj = this._wrapped;
|
|
43933
|
-
var newObj = clone(obj);
|
|
43934
|
-
var ops = dispatch(obj);
|
|
43935
|
-
if (lensArr.length === 0) {
|
|
43936
|
-
this._wrapped = f(this._wrapped);
|
|
43937
|
-
} else if (lensArr.length === 1) {
|
|
43938
|
-
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
43939
|
-
} else {
|
|
43940
|
-
var monocle = lensArr[0];
|
|
43941
|
-
var shortLens = lensArr.slice(1);
|
|
43942
|
-
|
|
43943
|
-
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
43944
|
-
|
|
43945
|
-
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
43946
|
-
this._wrapped = newObj;
|
|
43947
|
-
}
|
|
43948
|
-
return this;
|
|
43949
|
-
};
|
|
43950
|
-
|
|
43951
|
-
// TODO - move to individual files
|
|
43952
|
-
lens.prototype.merge = function (lensArr, props) {
|
|
43953
|
-
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
43954
|
-
return merge(oldProps, props);
|
|
43955
|
-
}).freeze();
|
|
43956
|
-
return this;
|
|
43957
|
-
};
|
|
43958
|
-
|
|
43959
|
-
// Lens must have length >= 1 or there would be nothing to return
|
|
43960
|
-
lens.prototype.del = function (lensArr) {
|
|
43961
|
-
var obj = this._wrapped;
|
|
43962
|
-
var ops = dispatch(obj);
|
|
43963
|
-
if (lensArr.length === 1) {
|
|
43964
|
-
this._wrapped = ops.del(obj, lensArr[0]);
|
|
43965
|
-
} else {
|
|
43966
|
-
var monocle = lensArr[0];
|
|
43967
|
-
var shortLens = lensArr.slice(1);
|
|
43968
|
-
var newObj = clone(obj);
|
|
43969
|
-
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
43970
|
-
this._wrapped = newObj;
|
|
43971
|
-
}
|
|
43972
|
-
return this;
|
|
43973
|
-
};
|
|
43974
|
-
lens.prototype.set = function (lensArr, set) {
|
|
43975
|
-
return this.mod(lensArr, function () {
|
|
43976
|
-
return set;
|
|
43977
|
-
});
|
|
43978
|
-
};
|
|
43979
|
-
|
|
43980
|
-
// ARRAY FUNCTIONS
|
|
43981
|
-
|
|
43982
|
-
const arr = {
|
|
43983
|
-
get: function (arr, monocle) {
|
|
43984
|
-
return arr[monocle];
|
|
43985
|
-
},
|
|
43986
|
-
set: function (arr, monocle, val) {
|
|
43987
|
-
var newArr = arr.splice();
|
|
43988
|
-
newArr[monocle] = val;
|
|
43989
|
-
return newArr;
|
|
43990
|
-
},
|
|
43991
|
-
mod: function (arr, monocle, f) {
|
|
43992
|
-
var newArr = arr.slice();
|
|
43993
|
-
newArr[monocle] = f(arr[monocle]);
|
|
43994
|
-
return newArr;
|
|
43995
|
-
},
|
|
43996
|
-
del: function (arr, monocle) {
|
|
43997
|
-
var newArr = arr.slice();
|
|
43998
|
-
newArr.splice(monocle, 1);
|
|
43999
|
-
return newArr;
|
|
44000
|
-
}
|
|
44001
|
-
};
|
|
44002
|
-
|
|
44003
|
-
/*
|
|
44004
|
-
// Lens must point to a member of an array. We'll insert into that array.
|
|
44005
|
-
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
44006
|
-
var obj = this._wrapped;
|
|
44007
|
-
|
|
44008
|
-
var arrLens = lensArr.slice(0, -1);
|
|
44009
|
-
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
44010
|
-
|
|
44011
|
-
var arrIdx = lensArr[lensArr.length-1];
|
|
44012
|
-
arr.splice(arrIdx, 0, toInsert);
|
|
44013
|
-
return lens(obj).set(arrLens, arr);
|
|
44014
|
-
};
|
|
44015
|
-
|
|
44016
|
-
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
44017
|
-
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
44018
|
-
var newLens = lensArr.slice();
|
|
44019
|
-
newLens[newLens.length-1] += 1;
|
|
44020
|
-
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
44021
|
-
};
|
|
44022
|
-
*/
|
|
44023
|
-
|
|
44024
|
-
// OBJECT FUNCTIONS
|
|
44025
|
-
|
|
44026
|
-
const obj = {
|
|
44027
|
-
get: function (obj, monocle) {
|
|
44028
|
-
return obj[monocle];
|
|
44029
|
-
},
|
|
44030
|
-
set: function (obj, monocle, val) {
|
|
44031
|
-
var newObj = clone(obj);
|
|
44032
|
-
newObj[monocle] = val;
|
|
44033
|
-
return newObj;
|
|
44034
|
-
},
|
|
44035
|
-
mod: function (obj, monocle, f) {
|
|
44036
|
-
var newObj = clone(obj);
|
|
44037
|
-
newObj[monocle] = f(obj[monocle]);
|
|
44038
|
-
return newObj;
|
|
44039
|
-
},
|
|
44040
|
-
del: function (obj, monocle) {
|
|
44041
|
-
var newObj = clone(obj);
|
|
44042
|
-
delete newObj[monocle];
|
|
44043
|
-
return newObj;
|
|
44044
|
-
}
|
|
44045
|
-
};
|
|
44046
|
-
|
|
44047
|
-
// STRING FUNCTIONS
|
|
44048
|
-
|
|
44049
|
-
const str = {
|
|
44050
|
-
get: function (arr, monocle) {
|
|
44051
|
-
return arr[monocle];
|
|
44052
|
-
},
|
|
44053
|
-
set: function (arr, monocle, val) {
|
|
44054
|
-
var newArr = arr.splice();
|
|
44055
|
-
newArr[monocle] = val;
|
|
44056
|
-
return newArr;
|
|
44057
|
-
},
|
|
44058
|
-
mod: function (arr, monocle, f) {
|
|
44059
|
-
var newArr = arr.splice();
|
|
44060
|
-
newArr[monocle] = f(arr[monocle]);
|
|
44061
|
-
return newArr;
|
|
44062
|
-
},
|
|
44063
|
-
del: function (arr, monocle) {
|
|
44064
|
-
var newArr = arr.slice();
|
|
44065
|
-
newArr.splice(monocle);
|
|
44066
|
-
return newArr;
|
|
44067
|
-
}
|
|
44068
|
-
};
|
|
44069
|
-
|
|
44070
|
-
/* eslint-disable eqeqeq, @typescript-eslint/no-unused-vars */
|
|
44071
|
-
/*
|
|
44072
|
-
* A class for formatting number to significant digits.
|
|
44073
|
-
* Copyright (C) 2001 Stephen Ostermiller
|
|
44074
|
-
* http://ostermiller.org/contact.pl?regarding?JavaScript+Significant+Figures
|
|
44075
|
-
*
|
|
44076
|
-
* This program is free software; you can redistribute it and/or modify
|
|
44077
|
-
* it under the terms of the GNU General Public License as published by
|
|
44078
|
-
* the Free Software Foundation; either version 2 of the License, or
|
|
44079
|
-
* (at your option) any later version.
|
|
44080
|
-
*
|
|
44081
|
-
* This program is distributed in the hope that it will be useful,
|
|
44082
|
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
44083
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
44084
|
-
* GNU General Public License for more details.
|
|
44085
|
-
*/
|
|
44086
|
-
|
|
44087
|
-
/**
|
|
44088
|
-
* An object tho both scans floating points to
|
|
44089
|
-
* determine the number of significant figures.
|
|
44090
|
-
* and can display a floating point using any number
|
|
44091
|
-
* of significant figures.
|
|
44092
|
-
*
|
|
44093
|
-
* @param s A string representation of a floating point.
|
|
44094
|
-
*/
|
|
44095
|
-
class SignificantFigures {
|
|
44096
|
-
constructor(s) {
|
|
44097
|
-
this.order = void 0;
|
|
44098
|
-
this.mantissa = void 0;
|
|
44099
|
-
this.positive = void 0;
|
|
44100
|
-
this.sigFigs = void 0;
|
|
44101
|
-
this.sigDecs = void 0;
|
|
44102
|
-
this.order = parseOrder(s);
|
|
44103
|
-
this.mantissa = parseMantissa(s);
|
|
44104
|
-
this.positive = parseSign(s);
|
|
44105
|
-
|
|
44106
|
-
/**
|
|
44107
|
-
* Get the number of significant figures this object uses.
|
|
44108
|
-
* Leading zeros are not significant. Traling zeros up to
|
|
44109
|
-
* and after the decimal point are significant.
|
|
44110
|
-
* Significant figures is good to know when the number is
|
|
44111
|
-
* used in multiplication.
|
|
44112
|
-
*
|
|
44113
|
-
* @return the number of significant figures.
|
|
44114
|
-
*/
|
|
44115
|
-
this.sigFigs = this.mantissa.length;
|
|
44116
|
-
|
|
44117
|
-
/**
|
|
44118
|
-
* Get the least significant decimal this object uses.
|
|
44119
|
-
* This is useful to know if a number is being used
|
|
44120
|
-
* in addition.
|
|
44121
|
-
* 400 - 2 the hundreds place (10^2) is the least significant decimal.
|
|
44122
|
-
* 75 - 0 the ones place (10^0) is the least significant decimal.
|
|
44123
|
-
* .543 - -3 the 1/1000's place (10^-3) is the least significant decimal.
|
|
44124
|
-
*
|
|
44125
|
-
* @return an integer representing the least significant decimal place.
|
|
44126
|
-
*/
|
|
44127
|
-
this.sigDecs = this.order - this.mantissa.length;
|
|
44128
|
-
}
|
|
44129
|
-
}
|
|
44130
|
-
|
|
44131
|
-
/**
|
|
44132
|
-
* Format a floating point for display using the specified
|
|
44133
|
-
* number of significant figures and least significant decimal.
|
|
44134
|
-
* Scientific notation may used by this method if this
|
|
44135
|
-
* object is very small, very large, has many significant
|
|
44136
|
-
* figures, or the number of significant figures would be
|
|
44137
|
-
* ambiguous in the output if scientific notation were not
|
|
44138
|
-
* used.
|
|
44139
|
-
*
|
|
44140
|
-
* @param f A floating point number that should be displayed
|
|
44141
|
-
* @param sigFigs desired number of significant figures (integer).
|
|
44142
|
-
* @param sigDecs the least significant decimal place (integer).
|
|
44143
|
-
* @param scientific true iff scientific notation should always be used.
|
|
44144
|
-
* @return a string of this object formatted correctly.
|
|
44145
|
-
*/
|
|
44146
|
-
function displaySigFigs(f, sigFigs, sigDecs, scientific) {
|
|
44147
|
-
const s = "" + f;
|
|
44148
|
-
let order = parseOrder(s);
|
|
44149
|
-
let mantissa = parseMantissa(s);
|
|
44150
|
-
let positive = parseSign(s);
|
|
44151
|
-
let add;
|
|
44152
|
-
let decAdd;
|
|
44153
|
-
let sigAdd;
|
|
44154
|
-
let zeroScientific = false;
|
|
44155
|
-
if (f == 0 || mantissa == "" || mantissa == "0") {
|
|
44156
|
-
mantissa = "";
|
|
44157
|
-
for (let i = 0; i < sigFigs; i++) {
|
|
44158
|
-
mantissa += "0";
|
|
44159
|
-
}
|
|
44160
|
-
order = sigFigs + sigDecs;
|
|
44161
|
-
if (sigDecs < 0 && -sigDecs >= sigFigs) {
|
|
44162
|
-
zeroScientific = true;
|
|
44163
|
-
}
|
|
44164
|
-
} else {
|
|
44165
|
-
decAdd = order - mantissa.length - sigDecs;
|
|
44166
|
-
sigAdd = sigFigs - mantissa.length;
|
|
44167
|
-
add = Math.min(sigAdd, decAdd);
|
|
44168
|
-
if (add < 0) {
|
|
44169
|
-
let rounded = round(mantissa, -add);
|
|
44170
|
-
if (rounded.length > mantissa.length + add) {
|
|
44171
|
-
order++;
|
|
44172
|
-
if (decAdd > sigAdd) {
|
|
44173
|
-
rounded = round(rounded, 1);
|
|
44174
|
-
}
|
|
44175
|
-
}
|
|
44176
|
-
mantissa = rounded;
|
|
44177
|
-
} else if (add > 0) {
|
|
44178
|
-
for (let i = 0; i < add; i++) {
|
|
44179
|
-
mantissa += "0";
|
|
44180
|
-
}
|
|
44181
|
-
}
|
|
44182
|
-
if (mantissa == "" || mantissa == "0") {
|
|
44183
|
-
mantissa = "0";
|
|
44184
|
-
positive = true;
|
|
44185
|
-
order = 1 + sigDecs;
|
|
44186
|
-
if (order != 0) {
|
|
44187
|
-
zeroScientific = true;
|
|
44188
|
-
}
|
|
44189
|
-
}
|
|
44190
|
-
}
|
|
44191
|
-
const useScientific = scientific || mantissa.length > 20 || order > 4 || order < -2 || order - mantissa.length > 0 && trailingZeros(mantissa) > 0 || zeroScientific;
|
|
44192
|
-
let returnVal = "";
|
|
44193
|
-
if (!positive) {
|
|
44194
|
-
returnVal += "-";
|
|
44195
|
-
}
|
|
44196
|
-
if (useScientific) {
|
|
44197
|
-
returnVal += mantissa.charAt(0);
|
|
44198
|
-
if (mantissa.length > 1) {
|
|
44199
|
-
returnVal += "." + mantissa.substring(1, mantissa.length);
|
|
44200
|
-
}
|
|
44201
|
-
if (order - 1 != 0) {
|
|
44202
|
-
returnVal += " x 10^" + (order - 1);
|
|
44203
|
-
}
|
|
44204
|
-
} else {
|
|
44205
|
-
let wholePart = "";
|
|
44206
|
-
let fractPart = "";
|
|
44207
|
-
let needDot = true;
|
|
44208
|
-
if (order > 0) {
|
|
44209
|
-
if (mantissa.length > order) {
|
|
44210
|
-
wholePart = mantissa.substring(0, order);
|
|
44211
|
-
fractPart = mantissa.substring(order, mantissa.length);
|
|
44212
|
-
} else {
|
|
44213
|
-
wholePart = mantissa;
|
|
44214
|
-
needDot = trailingZeros(mantissa) != 0;
|
|
44215
|
-
for (let i = 0; i < order - mantissa.length; i++) {
|
|
44216
|
-
wholePart += "0";
|
|
44217
|
-
}
|
|
44218
|
-
}
|
|
44219
|
-
} else {
|
|
44220
|
-
for (let i = 0; i < -order; i++) {
|
|
44221
|
-
fractPart += "0";
|
|
44222
|
-
}
|
|
44223
|
-
fractPart += mantissa;
|
|
44224
|
-
}
|
|
44225
|
-
returnVal += (wholePart == "" ? "0" : wholePart) + (needDot ? "." : "") + fractPart;
|
|
44226
|
-
}
|
|
44227
|
-
return returnVal;
|
|
44228
|
-
}
|
|
44229
|
-
|
|
44230
|
-
/**
|
|
44231
|
-
* Count the significant trailing zeros on this object.
|
|
44232
|
-
*
|
|
44233
|
-
* @return the number of trailing zeros
|
|
44234
|
-
*/
|
|
44235
|
-
function trailingZeros(mantissa) {
|
|
44236
|
-
let zeros = 0;
|
|
44237
|
-
for (let i = mantissa.length - 1; i >= 0; i--) {
|
|
44238
|
-
const c = mantissa.charAt(i);
|
|
44239
|
-
if (c == "0") {
|
|
44240
|
-
zeros++;
|
|
44241
|
-
} else {
|
|
44242
|
-
return zeros;
|
|
44243
|
-
}
|
|
44244
|
-
}
|
|
44245
|
-
return zeros;
|
|
44246
|
-
}
|
|
44247
|
-
|
|
44248
|
-
/**
|
|
44249
|
-
* Parse a string representation of a floating point
|
|
44250
|
-
* and pull out the sign.
|
|
44251
|
-
*
|
|
44252
|
-
* @param s the string representation of a floating point.
|
|
44253
|
-
* @return true iff this is a positive number
|
|
44254
|
-
*/
|
|
44255
|
-
function parseSign(s) {
|
|
44256
|
-
let beginning = true;
|
|
44257
|
-
let seenDot = false;
|
|
44258
|
-
let seenSomething = false;
|
|
44259
|
-
let zeros = "";
|
|
44260
|
-
let all = "";
|
|
44261
|
-
let pos = true;
|
|
44262
|
-
for (let i = 0; i < s.length; i++) {
|
|
44263
|
-
const c = s.charAt(i);
|
|
44264
|
-
if (c >= "1" && c <= "9") {
|
|
44265
|
-
all += zeros + c;
|
|
44266
|
-
zeros = "";
|
|
44267
|
-
seenSomething = true;
|
|
44268
|
-
beginning = false;
|
|
44269
|
-
} else if (c == "0") {
|
|
44270
|
-
if (seenDot) {
|
|
44271
|
-
if (seenSomething) {
|
|
44272
|
-
all += zeros + c;
|
|
44273
|
-
zeros = "";
|
|
44274
|
-
}
|
|
44275
|
-
} else {
|
|
44276
|
-
if (seenSomething) {
|
|
44277
|
-
zeros += c;
|
|
44278
|
-
}
|
|
44279
|
-
}
|
|
44280
|
-
beginning = false;
|
|
44281
|
-
} else if (!seenDot && c == ".") {
|
|
44282
|
-
all += zeros;
|
|
44283
|
-
zeros = "";
|
|
44284
|
-
seenDot = true;
|
|
44285
|
-
beginning = false;
|
|
44286
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44287
|
-
parseInt(s.substring(i + 1, s.length));
|
|
44288
|
-
i = s.length;
|
|
44289
|
-
} else if (beginning && (c == "+" || c == "-")) {
|
|
44290
|
-
if (c == "-") {
|
|
44291
|
-
pos = !pos;
|
|
44292
|
-
}
|
|
44293
|
-
}
|
|
44294
|
-
}
|
|
44295
|
-
if (all == "") {
|
|
44296
|
-
return true;
|
|
44297
|
-
}
|
|
44298
|
-
return pos;
|
|
44299
|
-
}
|
|
44300
|
-
|
|
44301
|
-
/**
|
|
44302
|
-
* Parse a string representation of a floating point
|
|
44303
|
-
* and pull out the mantissa.
|
|
44304
|
-
*
|
|
44305
|
-
* @param s the string representation of a floating point.
|
|
44306
|
-
* @return the mantissa of this number.
|
|
44307
|
-
*/
|
|
44308
|
-
function parseMantissa(s) {
|
|
44309
|
-
let seenDot = false;
|
|
44310
|
-
let seenSomething = false;
|
|
44311
|
-
let zeros = "";
|
|
44312
|
-
let leadZeros = "";
|
|
44313
|
-
let all = "";
|
|
44314
|
-
for (let i = 0; i < s.length; i++) {
|
|
44315
|
-
const c = s.charAt(i);
|
|
44316
|
-
if (c >= "1" && c <= "9") {
|
|
44317
|
-
all += zeros + c;
|
|
44318
|
-
zeros = "";
|
|
44319
|
-
seenSomething = true;
|
|
44320
|
-
} else if (c == "0") {
|
|
44321
|
-
if (seenDot) {
|
|
44322
|
-
if (seenSomething) {
|
|
44323
|
-
all += zeros + c;
|
|
44324
|
-
zeros = "";
|
|
44325
|
-
} else {
|
|
44326
|
-
leadZeros += c;
|
|
44327
|
-
}
|
|
44328
|
-
} else {
|
|
44329
|
-
if (seenSomething) {
|
|
44330
|
-
leadZeros += c;
|
|
44331
|
-
zeros += c;
|
|
44332
|
-
} else {
|
|
44333
|
-
leadZeros += c;
|
|
44334
|
-
}
|
|
44335
|
-
}
|
|
44336
|
-
} else if (!seenDot && c == ".") {
|
|
44337
|
-
all += zeros;
|
|
44338
|
-
zeros = "";
|
|
44339
|
-
seenDot = true;
|
|
44340
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44341
|
-
parseInt(s.substring(i + 1, s.length));
|
|
44342
|
-
i = s.length;
|
|
44343
|
-
} else ;
|
|
44344
|
-
}
|
|
44345
|
-
if (all == "") {
|
|
44346
|
-
return leadZeros;
|
|
44347
|
-
}
|
|
44348
|
-
return all;
|
|
44349
|
-
}
|
|
44350
|
-
|
|
44351
|
-
/**
|
|
44352
|
-
* Parse a string representation of a floating point
|
|
44353
|
-
* and pull out the exponent.
|
|
44354
|
-
*
|
|
44355
|
-
* @param s the string representation of a floating point.
|
|
44356
|
-
* @return (integer) the number after the e.
|
|
44357
|
-
*/
|
|
44358
|
-
function parseOrder(s) {
|
|
44359
|
-
let seenDot = false;
|
|
44360
|
-
let seenSomething = false;
|
|
44361
|
-
let zeros = "";
|
|
44362
|
-
let all = "";
|
|
44363
|
-
let decPlaces = 0;
|
|
44364
|
-
let totalDecs = 0;
|
|
44365
|
-
for (let i = 0; i < s.length; i++) {
|
|
44366
|
-
const c = s.charAt(i);
|
|
44367
|
-
if (c >= "1" && c <= "9") {
|
|
44368
|
-
all += zeros + c;
|
|
44369
|
-
zeros = "";
|
|
44370
|
-
seenSomething = true;
|
|
44371
|
-
if (!seenDot) {
|
|
44372
|
-
totalDecs++;
|
|
44373
|
-
decPlaces++;
|
|
44374
|
-
}
|
|
44375
|
-
} else if (c == "0") {
|
|
44376
|
-
if (seenDot) {
|
|
44377
|
-
if (seenSomething) {
|
|
44378
|
-
all += zeros + c;
|
|
44379
|
-
zeros = "";
|
|
44380
|
-
} else {
|
|
44381
|
-
decPlaces--;
|
|
44382
|
-
}
|
|
44383
|
-
} else {
|
|
44384
|
-
totalDecs++;
|
|
44385
|
-
if (seenSomething) {
|
|
44386
|
-
decPlaces++;
|
|
44387
|
-
zeros += c;
|
|
44388
|
-
}
|
|
44389
|
-
}
|
|
44390
|
-
} else if (!seenDot && c == ".") {
|
|
44391
|
-
all += zeros;
|
|
44392
|
-
zeros = "";
|
|
44393
|
-
seenDot = true;
|
|
44394
|
-
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
44395
|
-
const raised = parseInt(s.substring(i + 1, s.length));
|
|
44396
|
-
decPlaces += raised;
|
|
44397
|
-
totalDecs += raised;
|
|
44398
|
-
i = s.length;
|
|
44399
|
-
} else ;
|
|
44400
|
-
}
|
|
44401
|
-
if (all == "") {
|
|
44402
|
-
return totalDecs;
|
|
44403
|
-
}
|
|
44404
|
-
return decPlaces;
|
|
44405
|
-
}
|
|
44406
|
-
|
|
44407
|
-
/**
|
|
44408
|
-
* Remove the specified number of digits from string by
|
|
44409
|
-
* rounding. Proper rounding rules for scientific purposes
|
|
44410
|
-
* are followed.
|
|
44411
|
-
* This method may cause an extra significant figure
|
|
44412
|
-
* to be added to the number. For example, if 999999
|
|
44413
|
-
* were rounded, A one would carry over and become
|
|
44414
|
-
* a significant figure. Those who call this method
|
|
44415
|
-
* should check for this and call round again if needed.
|
|
44416
|
-
*
|
|
44417
|
-
* @param mantissa A string representing an whole number of arbitrary length.
|
|
44418
|
-
* @param digits A number of digits to remove
|
|
44419
|
-
* @return A string represted the rounded version of mantissa
|
|
44420
|
-
*/
|
|
44421
|
-
function round(mantissa, digits) {
|
|
44422
|
-
const last = mantissa.length - digits - 1;
|
|
44423
|
-
if (last < 0) {
|
|
44424
|
-
return "";
|
|
44425
|
-
}
|
|
44426
|
-
if (last >= mantissa.length - 1) {
|
|
44427
|
-
return mantissa;
|
|
44428
|
-
}
|
|
44429
|
-
const nextToLast = mantissa.charAt(last + 1);
|
|
44430
|
-
const lastChar = mantissa.charAt(last);
|
|
44431
|
-
let roundUp = false;
|
|
44432
|
-
if (nextToLast > "5") {
|
|
44433
|
-
roundUp = true;
|
|
44434
|
-
} else if (nextToLast == "5") {
|
|
44435
|
-
for (let j = last + 2; j < mantissa.length; j++) {
|
|
44436
|
-
if (mantissa.charAt(j) != "0") {
|
|
44437
|
-
roundUp = true;
|
|
44438
|
-
}
|
|
44439
|
-
}
|
|
44440
|
-
// @ts-expect-error - TS2362 - The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
|
|
44441
|
-
if (lastChar % 2 == 1) {
|
|
44442
|
-
roundUp = true;
|
|
44443
|
-
}
|
|
44444
|
-
}
|
|
44445
|
-
let result = "";
|
|
44446
|
-
for (let i = last; i >= 0; i--) {
|
|
44447
|
-
const c = mantissa.charAt(i);
|
|
44448
|
-
if (roundUp) {
|
|
44449
|
-
let nextChar;
|
|
44450
|
-
if (c == "9") {
|
|
44451
|
-
nextChar = "0";
|
|
44452
|
-
} else {
|
|
44453
|
-
switch (c) {
|
|
44454
|
-
case "0":
|
|
44455
|
-
nextChar = "1";
|
|
44456
|
-
break;
|
|
44457
|
-
case "1":
|
|
44458
|
-
nextChar = "2";
|
|
44459
|
-
break;
|
|
44460
|
-
case "2":
|
|
44461
|
-
nextChar = "3";
|
|
44462
|
-
break;
|
|
44463
|
-
case "3":
|
|
44464
|
-
nextChar = "4";
|
|
44465
|
-
break;
|
|
44466
|
-
case "4":
|
|
44467
|
-
nextChar = "5";
|
|
44468
|
-
break;
|
|
44469
|
-
case "5":
|
|
44470
|
-
nextChar = "6";
|
|
44471
|
-
break;
|
|
44472
|
-
case "6":
|
|
44473
|
-
nextChar = "7";
|
|
44474
|
-
break;
|
|
44475
|
-
case "7":
|
|
44476
|
-
nextChar = "8";
|
|
44477
|
-
break;
|
|
44478
|
-
case "8":
|
|
44479
|
-
nextChar = "9";
|
|
44480
|
-
break;
|
|
44481
|
-
}
|
|
44482
|
-
roundUp = false;
|
|
44483
|
-
}
|
|
44484
|
-
result = nextChar + result;
|
|
44485
|
-
} else {
|
|
44486
|
-
result = c + result;
|
|
44487
|
-
}
|
|
44488
|
-
}
|
|
44489
|
-
if (roundUp) {
|
|
44490
|
-
result = "1" + result;
|
|
44491
|
-
}
|
|
44492
|
-
return result;
|
|
44493
|
-
}
|
|
44494
|
-
|
|
44495
|
-
// TODO(joel): teach KAS how to accept an answer only if it's expressed in
|
|
44496
|
-
const ALL = "all";
|
|
44497
|
-
const countSigfigs = function countSigfigs(value) {
|
|
44498
|
-
return new SignificantFigures(value).sigFigs;
|
|
44499
|
-
};
|
|
44500
|
-
/* I just wrote this, but it's old by analogy to `OldExpression`, in that it's
|
|
44501
|
-
* the version that non-mathquill platforms get stuck with. Constructed with an
|
|
44502
|
-
* <input>, a parser, popsicle sticks, and glue.
|
|
44503
|
-
*
|
|
44504
|
-
* In the same way as OldExpression, this parses continuously as you type, then
|
|
44505
|
-
* shows and hides an error buddy. The error message is only shown after a
|
|
44506
|
-
* rolling two second delay, but hidden immediately on further typing.
|
|
44507
|
-
*/
|
|
44508
|
-
class OldUnitInput extends React.Component {
|
|
44509
|
-
constructor(..._args) {
|
|
44510
|
-
super(..._args);
|
|
44511
|
-
this._errorTimeout = void 0;
|
|
44512
|
-
this._showError = () => {
|
|
44513
|
-
if (this.props.value === "") {
|
|
44514
|
-
return;
|
|
44515
|
-
}
|
|
44516
|
-
|
|
44517
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44518
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44519
|
-
const $error = $(ReactDOM__default.findDOMNode(this.refs.error));
|
|
44520
|
-
// @ts-expect-error - TS2339 - Property 'is' does not exist on type 'JQueryStatic'.
|
|
44521
|
-
if (!$error.is(":visible")) {
|
|
44522
|
-
$error
|
|
44523
|
-
// @ts-expect-error - TS2554 - Expected 2 arguments, but got 1.
|
|
44524
|
-
.css({
|
|
44525
|
-
top: 50,
|
|
44526
|
-
opacity: 0.1
|
|
44527
|
-
}).show().animate({
|
|
44528
|
-
top: 0,
|
|
44529
|
-
opacity: 1.0
|
|
44530
|
-
}, 300);
|
|
44531
|
-
}
|
|
44532
|
-
};
|
|
44533
|
-
this._hideError = () => {
|
|
44534
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44535
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44536
|
-
const $error = $(ReactDOM__default.findDOMNode(this.refs.error));
|
|
44537
|
-
// @ts-expect-error - TS2339 - Property 'is' does not exist on type 'JQueryStatic'.
|
|
44538
|
-
if ($error.is(":visible")) {
|
|
44539
|
-
// @ts-expect-error - TS2339 - Property 'animate' does not exist on type 'JQueryStatic'.
|
|
44540
|
-
$error.animate({
|
|
44541
|
-
top: 50,
|
|
44542
|
-
opacity: 0.1
|
|
44543
|
-
}, 300, function () {
|
|
44544
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
44545
|
-
// @ts-expect-error - TS2683 - 'this' implicitly has type 'any' because it does not have a type annotation.
|
|
44546
|
-
// eslint-disable-next-line @babel/no-invalid-this
|
|
44547
|
-
$(this).hide();
|
|
44548
|
-
});
|
|
44549
|
-
}
|
|
44550
|
-
};
|
|
44551
|
-
this.change = (...args) => {
|
|
44552
|
-
// @ts-expect-error - TS2345 - Argument of type 'readonly any[]' is not assignable to parameter of type 'any[]'.
|
|
44553
|
-
return change.apply(this, args);
|
|
44554
|
-
};
|
|
44555
|
-
this.handleBlur = () => {
|
|
44556
|
-
this.props.onBlur([]);
|
|
44557
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44558
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44559
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44560
|
-
clearTimeout(this._errorTimeout);
|
|
44561
|
-
if (!KAS.unitParse(this.props.value).parsed) {
|
|
44562
|
-
this._showError();
|
|
44563
|
-
}
|
|
44564
|
-
};
|
|
44565
|
-
this.handleChange = event => {
|
|
44566
|
-
this._hideError();
|
|
44567
|
-
this.props.onChange({
|
|
44568
|
-
value: event.target.value
|
|
44569
|
-
});
|
|
44570
|
-
};
|
|
44571
|
-
this.simpleValidate = (rubric, onInputError) => {
|
|
44572
|
-
return OldUnitInput.validate(this.getUserInput(), rubric, this.context.strings);
|
|
44573
|
-
};
|
|
44574
|
-
this.getUserInput = () => {
|
|
44575
|
-
return this.props.value;
|
|
44576
|
-
};
|
|
44577
|
-
// begin mobile stuff
|
|
44578
|
-
this.getInputPaths = () => {
|
|
44579
|
-
// The widget itself is an input, so we return a single empty list to
|
|
44580
|
-
// indicate this.
|
|
44581
|
-
return [[]];
|
|
44582
|
-
};
|
|
44583
|
-
this.focusInputPath = inputPath => {
|
|
44584
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44585
|
-
const input = ReactDOM__default.findDOMNode(this.refs.input);
|
|
44586
|
-
if (input) {
|
|
44587
|
-
/**
|
|
44588
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
44589
|
-
* Change to using a ref callback so that focus() can be
|
|
44590
|
-
* accessed.
|
|
44591
|
-
*/
|
|
44592
|
-
// @ts-expect-error - TS2339 - Property 'focus' does not exist on type 'Element | Text'.
|
|
44593
|
-
input.focus();
|
|
44594
|
-
}
|
|
44595
|
-
};
|
|
44596
|
-
this.handleFocus = () => {
|
|
44597
|
-
this.props.onFocus([]);
|
|
44598
|
-
};
|
|
44599
|
-
this.blurInputPath = inputPath => {
|
|
44600
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44601
|
-
const input = ReactDOM__default.findDOMNode(this.refs.input);
|
|
44602
|
-
if (input) {
|
|
44603
|
-
/**
|
|
44604
|
-
* TODO(somewhatabstract, JIRA-XXXX):
|
|
44605
|
-
* Change to using a ref callback so that focus() can be
|
|
44606
|
-
* accessed.
|
|
44607
|
-
*/
|
|
44608
|
-
// @ts-expect-error - TS2339 - Property 'blur' does not exist on type 'Element | Text'.
|
|
44609
|
-
input.blur();
|
|
44610
|
-
}
|
|
44611
|
-
};
|
|
44612
|
-
this.setInputValue = (path, newValue, cb) => {
|
|
44613
|
-
this.props.onChange({
|
|
44614
|
-
value: newValue
|
|
44615
|
-
}, cb);
|
|
44616
|
-
};
|
|
44617
|
-
this.getDOMNodeForPath = () => {
|
|
44618
|
-
// eslint-disable-next-line react/no-string-refs
|
|
44619
|
-
return ReactDOM__default.findDOMNode(this.refs.input);
|
|
44620
|
-
};
|
|
44621
|
-
this.getGrammarTypeForPath = inputPath => {
|
|
44622
|
-
return "unit";
|
|
44623
|
-
};
|
|
44624
|
-
}
|
|
44625
|
-
static validate(userInput, rubric, strings) {
|
|
44626
|
-
const answer = KAS.unitParse(rubric.value).expr;
|
|
44627
|
-
const guess = KAS.unitParse(userInput);
|
|
44628
|
-
if (!guess.parsed) {
|
|
44629
|
-
return {
|
|
44630
|
-
type: "invalid",
|
|
44631
|
-
message: strings.dontUnderstandUnits
|
|
44632
|
-
};
|
|
44633
|
-
}
|
|
44634
|
-
|
|
44635
|
-
// Note: we check sigfigs, then numerical correctness, then units, so
|
|
44636
|
-
// the most significant things come last, that way the user will see
|
|
44637
|
-
// the most important message.
|
|
44638
|
-
let message = null;
|
|
44639
|
-
|
|
44640
|
-
// did the user specify the right number of sigfigs?
|
|
44641
|
-
// TODO(joel) - add a grading mode where the wrong number of sigfigs
|
|
44642
|
-
// isn't marked wrong
|
|
44643
|
-
const sigfigs = rubric.sigfigs;
|
|
44644
|
-
const sigfigsCorrect = countSigfigs(guess.coefficient) === sigfigs;
|
|
44645
|
-
if (!sigfigsCorrect) {
|
|
44646
|
-
message = strings.checkSigFigs;
|
|
44647
|
-
}
|
|
44648
|
-
|
|
44649
|
-
// now we need to check that the answer is correct to the precision we
|
|
44650
|
-
// require.
|
|
44651
|
-
let numericallyCorrect;
|
|
44652
|
-
try {
|
|
44653
|
-
const x = new KAS.Var("x");
|
|
44654
|
-
const equality = new KAS.Eq(answer.simplify(), "=", new KAS.Mul(x, guess.expr.simplify()));
|
|
44655
|
-
const conversion = equality.solveLinearEquationForVariable(x);
|
|
44656
|
-
|
|
44657
|
-
// Make sure the conversion factor between the user's input answer
|
|
44658
|
-
// and the canonical answer is 1, to sigfig places.
|
|
44659
|
-
// TODO(joel) is this sound?
|
|
44660
|
-
numericallyCorrect = Number(conversion.eval()).toPrecision(sigfigs) === Number(1).toPrecision(sigfigs);
|
|
44661
|
-
} catch (e) {
|
|
44662
|
-
numericallyCorrect = false;
|
|
44663
|
-
}
|
|
44664
|
-
if (!numericallyCorrect) {
|
|
44665
|
-
message = strings.answerNumericallyIncorrect;
|
|
44666
|
-
}
|
|
44667
|
-
let kasCorrect;
|
|
44668
|
-
const guessUnit = primUnits(guess.expr.simplify());
|
|
44669
|
-
const answerUnit = primUnits(answer.simplify());
|
|
44670
|
-
if (rubric.accepting === ALL) {
|
|
44671
|
-
// We're accepting all units - KAS does the hard work of figuring
|
|
44672
|
-
// out if the user's unit is equivalent to the author's unit.
|
|
44673
|
-
kasCorrect = KAS.compare(guessUnit, answerUnit).equal;
|
|
44674
|
-
} else {
|
|
44675
|
-
// Are any of the accepted units the same as what the user entered?
|
|
44676
|
-
kasCorrect = _(rubric.acceptingUnits).any(unit => {
|
|
44677
|
-
const thisAnswerUnit = primUnits(KAS.unitParse(unit).unit.simplify());
|
|
44678
|
-
return KAS.compare(thisAnswerUnit, guessUnit
|
|
44679
|
-
// TODO(joel) - make this work as intended.
|
|
44680
|
-
// { form: true }
|
|
44681
|
-
).equal;
|
|
44682
|
-
});
|
|
44683
|
-
}
|
|
44684
|
-
if (!kasCorrect) {
|
|
44685
|
-
message = strings.checkUnits;
|
|
44686
|
-
}
|
|
44687
|
-
const correct = kasCorrect && numericallyCorrect && sigfigsCorrect;
|
|
44688
|
-
return {
|
|
44689
|
-
type: "points",
|
|
44690
|
-
earned: correct ? 1 : 0,
|
|
44691
|
-
total: 1,
|
|
44692
|
-
message
|
|
44693
|
-
};
|
|
44694
|
-
}
|
|
44695
|
-
componentDidUpdate() {
|
|
44696
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44697
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44698
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44699
|
-
clearTimeout(this._errorTimeout);
|
|
44700
|
-
if (KAS.unitParse(this.props.value).parsed) {
|
|
44701
|
-
this._hideError();
|
|
44702
|
-
} else {
|
|
44703
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44704
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44705
|
-
// @ts-expect-error - TS2322 - Type 'Timeout' is not assignable to type 'number'.
|
|
44706
|
-
this._errorTimeout = setTimeout(this._showError, 2000);
|
|
44707
|
-
}
|
|
44708
|
-
}
|
|
44709
|
-
componentWillUnmount() {
|
|
44710
|
-
// TODO(jeff, CP-3128): Use Wonder Blocks Timing API.
|
|
44711
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
44712
|
-
// @ts-expect-error - TS2769 - No overload matches this call.
|
|
44713
|
-
clearTimeout(this._errorTimeout);
|
|
44714
|
-
}
|
|
44715
|
-
// end mobile stuff
|
|
44716
|
-
// TODO(joel) think about showing the error buddy
|
|
44717
|
-
render() {
|
|
44718
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
44719
|
-
className: "old-unit-input"
|
|
44720
|
-
}, /*#__PURE__*/React.createElement("input", {
|
|
44721
|
-
onChange: this.handleChange,
|
|
44722
|
-
ref: "input" // eslint-disable-line react/no-string-refs
|
|
44723
|
-
,
|
|
44724
|
-
className: ClassNames.INTERACTIVE,
|
|
44725
|
-
value: this.props.value,
|
|
44726
|
-
onFocus: this.handleFocus,
|
|
44727
|
-
onBlur: this.handleBlur
|
|
44728
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
44729
|
-
ref: "error",
|
|
44730
|
-
className: "error",
|
|
44731
|
-
style: {
|
|
44732
|
-
display: "none"
|
|
44733
|
-
}
|
|
44734
|
-
}, this.context.strings.dontUnderstand));
|
|
44735
|
-
}
|
|
44736
|
-
}
|
|
44737
|
-
|
|
44738
|
-
// Extract the primitive units from a unit expression. This first simplifies
|
|
44739
|
-
// `expr` to a `Mul` like "5 kg m / s^2" then removes the first term.
|
|
44740
|
-
OldUnitInput.contextType = PerseusI18nContext;
|
|
44741
|
-
OldUnitInput.defaultProps = {
|
|
44742
|
-
apiOptions: ApiOptions.defaults,
|
|
44743
|
-
value: ""
|
|
44744
|
-
};
|
|
44745
|
-
const primUnits = function primUnits(expr) {
|
|
44746
|
-
return expr.simplify().asMul().partition()[1].flatten().simplify();
|
|
44747
|
-
};
|
|
44748
|
-
var Unit = {
|
|
44749
|
-
name: "unit-input",
|
|
44750
|
-
displayName: "Unit input",
|
|
44751
|
-
defaultAlignment: "inline-block",
|
|
44752
|
-
widget: OldUnitInput,
|
|
44753
|
-
transform: x => lens(x).del(["value"]).freeze(),
|
|
44754
|
-
version: {
|
|
44755
|
-
major: 0,
|
|
44756
|
-
minor: 1
|
|
44757
|
-
},
|
|
44758
|
-
hidden: true
|
|
44759
|
-
};
|
|
44760
|
-
|
|
44761
43880
|
/**
|
|
44762
43881
|
* This is a component that adds a link to the transcript for embedded videos in articles.
|
|
44763
43882
|
*/
|
|
@@ -44930,7 +44049,7 @@ var Video$1 = {
|
|
|
44930
44049
|
};
|
|
44931
44050
|
|
|
44932
44051
|
/* eslint-disable import/no-named-as-default */
|
|
44933
|
-
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,
|
|
44052
|
+
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];
|
|
44934
44053
|
|
|
44935
44054
|
/**
|
|
44936
44055
|
* This should be called by all clients, specifying whether extra widgets are
|
|
@@ -44970,7 +44089,7 @@ const init = function init(options) {
|
|
|
44970
44089
|
|
|
44971
44090
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
44972
44091
|
const libName = "@khanacademy/perseus";
|
|
44973
|
-
const libVersion = "
|
|
44092
|
+
const libVersion = "27.0.0";
|
|
44974
44093
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
44975
44094
|
|
|
44976
44095
|
const apiVersion = {
|
|
@@ -45212,6 +44331,7 @@ class HintRenderer extends React.Component {
|
|
|
45212
44331
|
// eslint-disable-next-line react/no-string-refs
|
|
45213
44332
|
, {
|
|
45214
44333
|
ref: "renderer",
|
|
44334
|
+
hintMode: true,
|
|
45215
44335
|
widgets: hint.widgets,
|
|
45216
44336
|
content: hint.content || "",
|
|
45217
44337
|
images: hint.images,
|
|
@@ -46519,6 +45639,223 @@ function treeToItem(node) {
|
|
|
46519
45639
|
};
|
|
46520
45640
|
}
|
|
46521
45641
|
|
|
45642
|
+
var isObject = function isObject(obj) {
|
|
45643
|
+
return obj === Object(obj);
|
|
45644
|
+
};
|
|
45645
|
+
var merge = function merge() {
|
|
45646
|
+
var obj = {};
|
|
45647
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
45648
|
+
var source = arguments[i];
|
|
45649
|
+
if (source) {
|
|
45650
|
+
for (var prop in source) {
|
|
45651
|
+
obj[prop] = source[prop];
|
|
45652
|
+
}
|
|
45653
|
+
}
|
|
45654
|
+
}
|
|
45655
|
+
return obj;
|
|
45656
|
+
};
|
|
45657
|
+
var clone = function clone(obj) {
|
|
45658
|
+
if (!isObject(obj)) {
|
|
45659
|
+
return obj;
|
|
45660
|
+
}
|
|
45661
|
+
return Array.isArray(obj) ? obj.slice() : merge(obj);
|
|
45662
|
+
};
|
|
45663
|
+
|
|
45664
|
+
/* TODO batch *all* mutations
|
|
45665
|
+
* idea: freeze / thaw implementations for all types
|
|
45666
|
+
* lens constructor thaws, freeze delegates to type's freeze
|
|
45667
|
+
*/
|
|
45668
|
+
|
|
45669
|
+
// equivalents, without requiring it
|
|
45670
|
+
// find the implementation to use for a given object
|
|
45671
|
+
var dispatch = function dispatch(x) {
|
|
45672
|
+
if (Array.isArray(x)) {
|
|
45673
|
+
return arr;
|
|
45674
|
+
} else if (isObject(x)) {
|
|
45675
|
+
return obj;
|
|
45676
|
+
} else if (typeof x === "string") {
|
|
45677
|
+
return str;
|
|
45678
|
+
}
|
|
45679
|
+
};
|
|
45680
|
+
|
|
45681
|
+
// This is underscore with a different name
|
|
45682
|
+
var lens = function lens(obj) {
|
|
45683
|
+
if (obj instanceof lens) {
|
|
45684
|
+
return obj;
|
|
45685
|
+
}
|
|
45686
|
+
if (!(this instanceof lens)) {
|
|
45687
|
+
return new lens(obj);
|
|
45688
|
+
}
|
|
45689
|
+
var ops = dispatch(obj);
|
|
45690
|
+
this._wrapped = ops.thaw ? ops.thaw(obj) : obj;
|
|
45691
|
+
};
|
|
45692
|
+
lens.prototype.freeze = function () {
|
|
45693
|
+
var obj = this._wrapped;
|
|
45694
|
+
var ops = dispatch(obj);
|
|
45695
|
+
return ops.freeze ? ops.freeze(obj) : obj;
|
|
45696
|
+
};
|
|
45697
|
+
lens.prototype.zoom = function (lensArr) {
|
|
45698
|
+
if (this._zoomStack === undefined) {
|
|
45699
|
+
this._zoomStack = [];
|
|
45700
|
+
}
|
|
45701
|
+
this._zoomStack.push({
|
|
45702
|
+
zoom: lensArr,
|
|
45703
|
+
wrapped: this._wrapped
|
|
45704
|
+
});
|
|
45705
|
+
this._wrapped = lens(this._wrapped).get(lensArr);
|
|
45706
|
+
return this;
|
|
45707
|
+
};
|
|
45708
|
+
lens.prototype.deZoom = function () {
|
|
45709
|
+
var frame = this._zoomStack.pop();
|
|
45710
|
+
this._wrapped = lens(frame.wrapped).set(frame.zoom, this._wrapped).freeze();
|
|
45711
|
+
return this;
|
|
45712
|
+
};
|
|
45713
|
+
lens.prototype.get = function (lensArr) {
|
|
45714
|
+
var obj = this._wrapped;
|
|
45715
|
+
for (var i = 0; i < lensArr.length; i++) {
|
|
45716
|
+
obj = dispatch(obj).get(obj, lensArr[i]);
|
|
45717
|
+
}
|
|
45718
|
+
return obj;
|
|
45719
|
+
};
|
|
45720
|
+
lens.prototype.mod = function (lensArr, f) {
|
|
45721
|
+
var obj = this._wrapped;
|
|
45722
|
+
var newObj = clone(obj);
|
|
45723
|
+
var ops = dispatch(obj);
|
|
45724
|
+
if (lensArr.length === 0) {
|
|
45725
|
+
this._wrapped = f(this._wrapped);
|
|
45726
|
+
} else if (lensArr.length === 1) {
|
|
45727
|
+
this._wrapped = ops.mod(newObj, lensArr[0], f);
|
|
45728
|
+
} else {
|
|
45729
|
+
var monocle = lensArr[0];
|
|
45730
|
+
var shortLens = lensArr.slice(1);
|
|
45731
|
+
|
|
45732
|
+
// newObj = ops.mod(obj[monocle], shortLens, f);
|
|
45733
|
+
|
|
45734
|
+
newObj[monocle] = lens(obj[monocle]).mod(shortLens, f).freeze();
|
|
45735
|
+
this._wrapped = newObj;
|
|
45736
|
+
}
|
|
45737
|
+
return this;
|
|
45738
|
+
};
|
|
45739
|
+
|
|
45740
|
+
// TODO - move to individual files
|
|
45741
|
+
lens.prototype.merge = function (lensArr, props) {
|
|
45742
|
+
this._wrapped = lens(this._wrapped).mod(lensArr, function (oldProps) {
|
|
45743
|
+
return merge(oldProps, props);
|
|
45744
|
+
}).freeze();
|
|
45745
|
+
return this;
|
|
45746
|
+
};
|
|
45747
|
+
|
|
45748
|
+
// Lens must have length >= 1 or there would be nothing to return
|
|
45749
|
+
lens.prototype.del = function (lensArr) {
|
|
45750
|
+
var obj = this._wrapped;
|
|
45751
|
+
var ops = dispatch(obj);
|
|
45752
|
+
if (lensArr.length === 1) {
|
|
45753
|
+
this._wrapped = ops.del(obj, lensArr[0]);
|
|
45754
|
+
} else {
|
|
45755
|
+
var monocle = lensArr[0];
|
|
45756
|
+
var shortLens = lensArr.slice(1);
|
|
45757
|
+
var newObj = clone(obj);
|
|
45758
|
+
newObj[monocle] = lens(obj[monocle]).del(shortLens).freeze();
|
|
45759
|
+
this._wrapped = newObj;
|
|
45760
|
+
}
|
|
45761
|
+
return this;
|
|
45762
|
+
};
|
|
45763
|
+
lens.prototype.set = function (lensArr, set) {
|
|
45764
|
+
return this.mod(lensArr, function () {
|
|
45765
|
+
return set;
|
|
45766
|
+
});
|
|
45767
|
+
};
|
|
45768
|
+
|
|
45769
|
+
// ARRAY FUNCTIONS
|
|
45770
|
+
|
|
45771
|
+
const arr = {
|
|
45772
|
+
get: function (arr, monocle) {
|
|
45773
|
+
return arr[monocle];
|
|
45774
|
+
},
|
|
45775
|
+
set: function (arr, monocle, val) {
|
|
45776
|
+
var newArr = arr.splice();
|
|
45777
|
+
newArr[monocle] = val;
|
|
45778
|
+
return newArr;
|
|
45779
|
+
},
|
|
45780
|
+
mod: function (arr, monocle, f) {
|
|
45781
|
+
var newArr = arr.slice();
|
|
45782
|
+
newArr[monocle] = f(arr[monocle]);
|
|
45783
|
+
return newArr;
|
|
45784
|
+
},
|
|
45785
|
+
del: function (arr, monocle) {
|
|
45786
|
+
var newArr = arr.slice();
|
|
45787
|
+
newArr.splice(monocle, 1);
|
|
45788
|
+
return newArr;
|
|
45789
|
+
}
|
|
45790
|
+
};
|
|
45791
|
+
|
|
45792
|
+
/*
|
|
45793
|
+
// Lens must point to a member of an array. We'll insert into that array.
|
|
45794
|
+
lens.prototype.insertAt = function(lensArr, toInsert) {
|
|
45795
|
+
var obj = this._wrapped;
|
|
45796
|
+
|
|
45797
|
+
var arrLens = lensArr.slice(0, -1);
|
|
45798
|
+
var arr = lens(obj).get(arrLens).slice(); // slice to copy
|
|
45799
|
+
|
|
45800
|
+
var arrIdx = lensArr[lensArr.length-1];
|
|
45801
|
+
arr.splice(arrIdx, 0, toInsert);
|
|
45802
|
+
return lens(obj).set(arrLens, arr);
|
|
45803
|
+
};
|
|
45804
|
+
|
|
45805
|
+
lens.prototype.insertBefore = lens.prototype.insertAt;
|
|
45806
|
+
lens.prototype.insertAfter = function(lensArr, toInsert) {
|
|
45807
|
+
var newLens = lensArr.slice();
|
|
45808
|
+
newLens[newLens.length-1] += 1;
|
|
45809
|
+
return lens(this._wrapped).insertAt(newLens, toInsert);
|
|
45810
|
+
};
|
|
45811
|
+
*/
|
|
45812
|
+
|
|
45813
|
+
// OBJECT FUNCTIONS
|
|
45814
|
+
|
|
45815
|
+
const obj = {
|
|
45816
|
+
get: function (obj, monocle) {
|
|
45817
|
+
return obj[monocle];
|
|
45818
|
+
},
|
|
45819
|
+
set: function (obj, monocle, val) {
|
|
45820
|
+
var newObj = clone(obj);
|
|
45821
|
+
newObj[monocle] = val;
|
|
45822
|
+
return newObj;
|
|
45823
|
+
},
|
|
45824
|
+
mod: function (obj, monocle, f) {
|
|
45825
|
+
var newObj = clone(obj);
|
|
45826
|
+
newObj[monocle] = f(obj[monocle]);
|
|
45827
|
+
return newObj;
|
|
45828
|
+
},
|
|
45829
|
+
del: function (obj, monocle) {
|
|
45830
|
+
var newObj = clone(obj);
|
|
45831
|
+
delete newObj[monocle];
|
|
45832
|
+
return newObj;
|
|
45833
|
+
}
|
|
45834
|
+
};
|
|
45835
|
+
|
|
45836
|
+
// STRING FUNCTIONS
|
|
45837
|
+
|
|
45838
|
+
const str = {
|
|
45839
|
+
get: function (arr, monocle) {
|
|
45840
|
+
return arr[monocle];
|
|
45841
|
+
},
|
|
45842
|
+
set: function (arr, monocle, val) {
|
|
45843
|
+
var newArr = arr.splice();
|
|
45844
|
+
newArr[monocle] = val;
|
|
45845
|
+
return newArr;
|
|
45846
|
+
},
|
|
45847
|
+
mod: function (arr, monocle, f) {
|
|
45848
|
+
var newArr = arr.splice();
|
|
45849
|
+
newArr[monocle] = f(arr[monocle]);
|
|
45850
|
+
return newArr;
|
|
45851
|
+
},
|
|
45852
|
+
del: function (arr, monocle) {
|
|
45853
|
+
var newArr = arr.slice();
|
|
45854
|
+
newArr.splice(monocle);
|
|
45855
|
+
return newArr;
|
|
45856
|
+
}
|
|
45857
|
+
};
|
|
45858
|
+
|
|
46522
45859
|
const _excluded = ["item", "children", "shape", "serializedState", "onSerializedStateUpdated"];
|
|
46523
45860
|
|
|
46524
45861
|
// TODO(mdr)
|
|
@@ -47118,6 +46455,372 @@ function violatingWidgets(itemData) {
|
|
|
47118
46455
|
return _.uniq(widgets);
|
|
47119
46456
|
}
|
|
47120
46457
|
|
|
46458
|
+
/* eslint-disable eqeqeq, @typescript-eslint/no-unused-vars */
|
|
46459
|
+
|
|
46460
|
+
/**
|
|
46461
|
+
* Format a floating point for display using the specified
|
|
46462
|
+
* number of significant figures and least significant decimal.
|
|
46463
|
+
* Scientific notation may used by this method if this
|
|
46464
|
+
* object is very small, very large, has many significant
|
|
46465
|
+
* figures, or the number of significant figures would be
|
|
46466
|
+
* ambiguous in the output if scientific notation were not
|
|
46467
|
+
* used.
|
|
46468
|
+
*
|
|
46469
|
+
* @param f A floating point number that should be displayed
|
|
46470
|
+
* @param sigFigs desired number of significant figures (integer).
|
|
46471
|
+
* @param sigDecs the least significant decimal place (integer).
|
|
46472
|
+
* @param scientific true iff scientific notation should always be used.
|
|
46473
|
+
* @return a string of this object formatted correctly.
|
|
46474
|
+
*/
|
|
46475
|
+
function displaySigFigs(f, sigFigs, sigDecs, scientific) {
|
|
46476
|
+
const s = "" + f;
|
|
46477
|
+
let order = parseOrder(s);
|
|
46478
|
+
let mantissa = parseMantissa(s);
|
|
46479
|
+
let positive = parseSign(s);
|
|
46480
|
+
let add;
|
|
46481
|
+
let decAdd;
|
|
46482
|
+
let sigAdd;
|
|
46483
|
+
let zeroScientific = false;
|
|
46484
|
+
if (f == 0 || mantissa == "" || mantissa == "0") {
|
|
46485
|
+
mantissa = "";
|
|
46486
|
+
for (let i = 0; i < sigFigs; i++) {
|
|
46487
|
+
mantissa += "0";
|
|
46488
|
+
}
|
|
46489
|
+
order = sigFigs + sigDecs;
|
|
46490
|
+
if (sigDecs < 0 && -sigDecs >= sigFigs) {
|
|
46491
|
+
zeroScientific = true;
|
|
46492
|
+
}
|
|
46493
|
+
} else {
|
|
46494
|
+
decAdd = order - mantissa.length - sigDecs;
|
|
46495
|
+
sigAdd = sigFigs - mantissa.length;
|
|
46496
|
+
add = Math.min(sigAdd, decAdd);
|
|
46497
|
+
if (add < 0) {
|
|
46498
|
+
let rounded = round(mantissa, -add);
|
|
46499
|
+
if (rounded.length > mantissa.length + add) {
|
|
46500
|
+
order++;
|
|
46501
|
+
if (decAdd > sigAdd) {
|
|
46502
|
+
rounded = round(rounded, 1);
|
|
46503
|
+
}
|
|
46504
|
+
}
|
|
46505
|
+
mantissa = rounded;
|
|
46506
|
+
} else if (add > 0) {
|
|
46507
|
+
for (let i = 0; i < add; i++) {
|
|
46508
|
+
mantissa += "0";
|
|
46509
|
+
}
|
|
46510
|
+
}
|
|
46511
|
+
if (mantissa == "" || mantissa == "0") {
|
|
46512
|
+
mantissa = "0";
|
|
46513
|
+
positive = true;
|
|
46514
|
+
order = 1 + sigDecs;
|
|
46515
|
+
if (order != 0) {
|
|
46516
|
+
zeroScientific = true;
|
|
46517
|
+
}
|
|
46518
|
+
}
|
|
46519
|
+
}
|
|
46520
|
+
const useScientific = scientific || mantissa.length > 20 || order > 4 || order < -2 || order - mantissa.length > 0 && trailingZeros(mantissa) > 0 || zeroScientific;
|
|
46521
|
+
let returnVal = "";
|
|
46522
|
+
if (!positive) {
|
|
46523
|
+
returnVal += "-";
|
|
46524
|
+
}
|
|
46525
|
+
if (useScientific) {
|
|
46526
|
+
returnVal += mantissa.charAt(0);
|
|
46527
|
+
if (mantissa.length > 1) {
|
|
46528
|
+
returnVal += "." + mantissa.substring(1, mantissa.length);
|
|
46529
|
+
}
|
|
46530
|
+
if (order - 1 != 0) {
|
|
46531
|
+
returnVal += " x 10^" + (order - 1);
|
|
46532
|
+
}
|
|
46533
|
+
} else {
|
|
46534
|
+
let wholePart = "";
|
|
46535
|
+
let fractPart = "";
|
|
46536
|
+
let needDot = true;
|
|
46537
|
+
if (order > 0) {
|
|
46538
|
+
if (mantissa.length > order) {
|
|
46539
|
+
wholePart = mantissa.substring(0, order);
|
|
46540
|
+
fractPart = mantissa.substring(order, mantissa.length);
|
|
46541
|
+
} else {
|
|
46542
|
+
wholePart = mantissa;
|
|
46543
|
+
needDot = trailingZeros(mantissa) != 0;
|
|
46544
|
+
for (let i = 0; i < order - mantissa.length; i++) {
|
|
46545
|
+
wholePart += "0";
|
|
46546
|
+
}
|
|
46547
|
+
}
|
|
46548
|
+
} else {
|
|
46549
|
+
for (let i = 0; i < -order; i++) {
|
|
46550
|
+
fractPart += "0";
|
|
46551
|
+
}
|
|
46552
|
+
fractPart += mantissa;
|
|
46553
|
+
}
|
|
46554
|
+
returnVal += (wholePart == "" ? "0" : wholePart) + (needDot ? "." : "") + fractPart;
|
|
46555
|
+
}
|
|
46556
|
+
return returnVal;
|
|
46557
|
+
}
|
|
46558
|
+
|
|
46559
|
+
/**
|
|
46560
|
+
* Count the significant trailing zeros on this object.
|
|
46561
|
+
*
|
|
46562
|
+
* @return the number of trailing zeros
|
|
46563
|
+
*/
|
|
46564
|
+
function trailingZeros(mantissa) {
|
|
46565
|
+
let zeros = 0;
|
|
46566
|
+
for (let i = mantissa.length - 1; i >= 0; i--) {
|
|
46567
|
+
const c = mantissa.charAt(i);
|
|
46568
|
+
if (c == "0") {
|
|
46569
|
+
zeros++;
|
|
46570
|
+
} else {
|
|
46571
|
+
return zeros;
|
|
46572
|
+
}
|
|
46573
|
+
}
|
|
46574
|
+
return zeros;
|
|
46575
|
+
}
|
|
46576
|
+
|
|
46577
|
+
/**
|
|
46578
|
+
* Parse a string representation of a floating point
|
|
46579
|
+
* and pull out the sign.
|
|
46580
|
+
*
|
|
46581
|
+
* @param s the string representation of a floating point.
|
|
46582
|
+
* @return true iff this is a positive number
|
|
46583
|
+
*/
|
|
46584
|
+
function parseSign(s) {
|
|
46585
|
+
let beginning = true;
|
|
46586
|
+
let seenDot = false;
|
|
46587
|
+
let seenSomething = false;
|
|
46588
|
+
let zeros = "";
|
|
46589
|
+
let all = "";
|
|
46590
|
+
let pos = true;
|
|
46591
|
+
for (let i = 0; i < s.length; i++) {
|
|
46592
|
+
const c = s.charAt(i);
|
|
46593
|
+
if (c >= "1" && c <= "9") {
|
|
46594
|
+
all += zeros + c;
|
|
46595
|
+
zeros = "";
|
|
46596
|
+
seenSomething = true;
|
|
46597
|
+
beginning = false;
|
|
46598
|
+
} else if (c == "0") {
|
|
46599
|
+
if (seenDot) {
|
|
46600
|
+
if (seenSomething) {
|
|
46601
|
+
all += zeros + c;
|
|
46602
|
+
zeros = "";
|
|
46603
|
+
}
|
|
46604
|
+
} else {
|
|
46605
|
+
if (seenSomething) {
|
|
46606
|
+
zeros += c;
|
|
46607
|
+
}
|
|
46608
|
+
}
|
|
46609
|
+
beginning = false;
|
|
46610
|
+
} else if (!seenDot && c == ".") {
|
|
46611
|
+
all += zeros;
|
|
46612
|
+
zeros = "";
|
|
46613
|
+
seenDot = true;
|
|
46614
|
+
beginning = false;
|
|
46615
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
46616
|
+
parseInt(s.substring(i + 1, s.length));
|
|
46617
|
+
i = s.length;
|
|
46618
|
+
} else if (beginning && (c == "+" || c == "-")) {
|
|
46619
|
+
if (c == "-") {
|
|
46620
|
+
pos = !pos;
|
|
46621
|
+
}
|
|
46622
|
+
}
|
|
46623
|
+
}
|
|
46624
|
+
if (all == "") {
|
|
46625
|
+
return true;
|
|
46626
|
+
}
|
|
46627
|
+
return pos;
|
|
46628
|
+
}
|
|
46629
|
+
|
|
46630
|
+
/**
|
|
46631
|
+
* Parse a string representation of a floating point
|
|
46632
|
+
* and pull out the mantissa.
|
|
46633
|
+
*
|
|
46634
|
+
* @param s the string representation of a floating point.
|
|
46635
|
+
* @return the mantissa of this number.
|
|
46636
|
+
*/
|
|
46637
|
+
function parseMantissa(s) {
|
|
46638
|
+
let seenDot = false;
|
|
46639
|
+
let seenSomething = false;
|
|
46640
|
+
let zeros = "";
|
|
46641
|
+
let leadZeros = "";
|
|
46642
|
+
let all = "";
|
|
46643
|
+
for (let i = 0; i < s.length; i++) {
|
|
46644
|
+
const c = s.charAt(i);
|
|
46645
|
+
if (c >= "1" && c <= "9") {
|
|
46646
|
+
all += zeros + c;
|
|
46647
|
+
zeros = "";
|
|
46648
|
+
seenSomething = true;
|
|
46649
|
+
} else if (c == "0") {
|
|
46650
|
+
if (seenDot) {
|
|
46651
|
+
if (seenSomething) {
|
|
46652
|
+
all += zeros + c;
|
|
46653
|
+
zeros = "";
|
|
46654
|
+
} else {
|
|
46655
|
+
leadZeros += c;
|
|
46656
|
+
}
|
|
46657
|
+
} else {
|
|
46658
|
+
if (seenSomething) {
|
|
46659
|
+
leadZeros += c;
|
|
46660
|
+
zeros += c;
|
|
46661
|
+
} else {
|
|
46662
|
+
leadZeros += c;
|
|
46663
|
+
}
|
|
46664
|
+
}
|
|
46665
|
+
} else if (!seenDot && c == ".") {
|
|
46666
|
+
all += zeros;
|
|
46667
|
+
zeros = "";
|
|
46668
|
+
seenDot = true;
|
|
46669
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
46670
|
+
parseInt(s.substring(i + 1, s.length));
|
|
46671
|
+
i = s.length;
|
|
46672
|
+
} else ;
|
|
46673
|
+
}
|
|
46674
|
+
if (all == "") {
|
|
46675
|
+
return leadZeros;
|
|
46676
|
+
}
|
|
46677
|
+
return all;
|
|
46678
|
+
}
|
|
46679
|
+
|
|
46680
|
+
/**
|
|
46681
|
+
* Parse a string representation of a floating point
|
|
46682
|
+
* and pull out the exponent.
|
|
46683
|
+
*
|
|
46684
|
+
* @param s the string representation of a floating point.
|
|
46685
|
+
* @return (integer) the number after the e.
|
|
46686
|
+
*/
|
|
46687
|
+
function parseOrder(s) {
|
|
46688
|
+
let seenDot = false;
|
|
46689
|
+
let seenSomething = false;
|
|
46690
|
+
let zeros = "";
|
|
46691
|
+
let all = "";
|
|
46692
|
+
let decPlaces = 0;
|
|
46693
|
+
let totalDecs = 0;
|
|
46694
|
+
for (let i = 0; i < s.length; i++) {
|
|
46695
|
+
const c = s.charAt(i);
|
|
46696
|
+
if (c >= "1" && c <= "9") {
|
|
46697
|
+
all += zeros + c;
|
|
46698
|
+
zeros = "";
|
|
46699
|
+
seenSomething = true;
|
|
46700
|
+
if (!seenDot) {
|
|
46701
|
+
totalDecs++;
|
|
46702
|
+
decPlaces++;
|
|
46703
|
+
}
|
|
46704
|
+
} else if (c == "0") {
|
|
46705
|
+
if (seenDot) {
|
|
46706
|
+
if (seenSomething) {
|
|
46707
|
+
all += zeros + c;
|
|
46708
|
+
zeros = "";
|
|
46709
|
+
} else {
|
|
46710
|
+
decPlaces--;
|
|
46711
|
+
}
|
|
46712
|
+
} else {
|
|
46713
|
+
totalDecs++;
|
|
46714
|
+
if (seenSomething) {
|
|
46715
|
+
decPlaces++;
|
|
46716
|
+
zeros += c;
|
|
46717
|
+
}
|
|
46718
|
+
}
|
|
46719
|
+
} else if (!seenDot && c == ".") {
|
|
46720
|
+
all += zeros;
|
|
46721
|
+
zeros = "";
|
|
46722
|
+
seenDot = true;
|
|
46723
|
+
} else if (c == "e" || c == "E" && i + 1 < s.length) {
|
|
46724
|
+
const raised = parseInt(s.substring(i + 1, s.length));
|
|
46725
|
+
decPlaces += raised;
|
|
46726
|
+
totalDecs += raised;
|
|
46727
|
+
i = s.length;
|
|
46728
|
+
} else ;
|
|
46729
|
+
}
|
|
46730
|
+
if (all == "") {
|
|
46731
|
+
return totalDecs;
|
|
46732
|
+
}
|
|
46733
|
+
return decPlaces;
|
|
46734
|
+
}
|
|
46735
|
+
|
|
46736
|
+
/**
|
|
46737
|
+
* Remove the specified number of digits from string by
|
|
46738
|
+
* rounding. Proper rounding rules for scientific purposes
|
|
46739
|
+
* are followed.
|
|
46740
|
+
* This method may cause an extra significant figure
|
|
46741
|
+
* to be added to the number. For example, if 999999
|
|
46742
|
+
* were rounded, A one would carry over and become
|
|
46743
|
+
* a significant figure. Those who call this method
|
|
46744
|
+
* should check for this and call round again if needed.
|
|
46745
|
+
*
|
|
46746
|
+
* @param mantissa A string representing an whole number of arbitrary length.
|
|
46747
|
+
* @param digits A number of digits to remove
|
|
46748
|
+
* @return A string represted the rounded version of mantissa
|
|
46749
|
+
*/
|
|
46750
|
+
function round(mantissa, digits) {
|
|
46751
|
+
const last = mantissa.length - digits - 1;
|
|
46752
|
+
if (last < 0) {
|
|
46753
|
+
return "";
|
|
46754
|
+
}
|
|
46755
|
+
if (last >= mantissa.length - 1) {
|
|
46756
|
+
return mantissa;
|
|
46757
|
+
}
|
|
46758
|
+
const nextToLast = mantissa.charAt(last + 1);
|
|
46759
|
+
const lastChar = mantissa.charAt(last);
|
|
46760
|
+
let roundUp = false;
|
|
46761
|
+
if (nextToLast > "5") {
|
|
46762
|
+
roundUp = true;
|
|
46763
|
+
} else if (nextToLast == "5") {
|
|
46764
|
+
for (let j = last + 2; j < mantissa.length; j++) {
|
|
46765
|
+
if (mantissa.charAt(j) != "0") {
|
|
46766
|
+
roundUp = true;
|
|
46767
|
+
}
|
|
46768
|
+
}
|
|
46769
|
+
// @ts-expect-error - TS2362 - The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
|
|
46770
|
+
if (lastChar % 2 == 1) {
|
|
46771
|
+
roundUp = true;
|
|
46772
|
+
}
|
|
46773
|
+
}
|
|
46774
|
+
let result = "";
|
|
46775
|
+
for (let i = last; i >= 0; i--) {
|
|
46776
|
+
const c = mantissa.charAt(i);
|
|
46777
|
+
if (roundUp) {
|
|
46778
|
+
let nextChar;
|
|
46779
|
+
if (c == "9") {
|
|
46780
|
+
nextChar = "0";
|
|
46781
|
+
} else {
|
|
46782
|
+
switch (c) {
|
|
46783
|
+
case "0":
|
|
46784
|
+
nextChar = "1";
|
|
46785
|
+
break;
|
|
46786
|
+
case "1":
|
|
46787
|
+
nextChar = "2";
|
|
46788
|
+
break;
|
|
46789
|
+
case "2":
|
|
46790
|
+
nextChar = "3";
|
|
46791
|
+
break;
|
|
46792
|
+
case "3":
|
|
46793
|
+
nextChar = "4";
|
|
46794
|
+
break;
|
|
46795
|
+
case "4":
|
|
46796
|
+
nextChar = "5";
|
|
46797
|
+
break;
|
|
46798
|
+
case "5":
|
|
46799
|
+
nextChar = "6";
|
|
46800
|
+
break;
|
|
46801
|
+
case "6":
|
|
46802
|
+
nextChar = "7";
|
|
46803
|
+
break;
|
|
46804
|
+
case "7":
|
|
46805
|
+
nextChar = "8";
|
|
46806
|
+
break;
|
|
46807
|
+
case "8":
|
|
46808
|
+
nextChar = "9";
|
|
46809
|
+
break;
|
|
46810
|
+
}
|
|
46811
|
+
roundUp = false;
|
|
46812
|
+
}
|
|
46813
|
+
result = nextChar + result;
|
|
46814
|
+
} else {
|
|
46815
|
+
result = c + result;
|
|
46816
|
+
}
|
|
46817
|
+
}
|
|
46818
|
+
if (roundUp) {
|
|
46819
|
+
result = "1" + result;
|
|
46820
|
+
}
|
|
46821
|
+
return result;
|
|
46822
|
+
}
|
|
46823
|
+
|
|
47121
46824
|
/**
|
|
47122
46825
|
* Some tests require some or all of the widgets and editors to be registered
|
|
47123
46826
|
* in order for them to work. Requiring this file will register all of the
|
|
@@ -47837,9 +47540,6 @@ function generateTestInteractiveGraphWidget() {
|
|
|
47837
47540
|
markings: "graph",
|
|
47838
47541
|
labels: ["x", "y"],
|
|
47839
47542
|
showProtractor: false,
|
|
47840
|
-
showRuler: false,
|
|
47841
|
-
rulerLabel: "mm",
|
|
47842
|
-
rulerTicks: 2,
|
|
47843
47543
|
range: [[-10, 10], [-10, 10]],
|
|
47844
47544
|
graph: {
|
|
47845
47545
|
type: "angle"
|
|
@@ -47951,7 +47651,6 @@ const widgetNameToEnum = {
|
|
|
47951
47651
|
simulator: "SIMULATOR",
|
|
47952
47652
|
sorter: "SORTER",
|
|
47953
47653
|
table: "TABLE",
|
|
47954
|
-
"unit-input": "UNIT",
|
|
47955
47654
|
video: "VIDEO"
|
|
47956
47655
|
};
|
|
47957
47656
|
function convertWidgetNameToEnum(name) {
|
|
@@ -47970,5 +47669,5 @@ const EditorJsonify = {
|
|
|
47970
47669
|
}
|
|
47971
47670
|
};
|
|
47972
47671
|
|
|
47973
|
-
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAnswerFromUserInput, getAnswersFromWidgets, getCorrectAnswerForWidgetId, getLineCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
47672
|
+
export { ApiOptions, ArrowPicker, ArticleRenderer, BaseRadio, Categorizer$1 as Categorizer, changeable as Changeable, ClassNames, ColorPicker, DashPicker, dependencies as Dependencies, EditorJsonify, ElementContainer, Expression, util as GrapherUtil, Grapher$1 as GrapherWidget, HintRenderer, HintsRenderer, InputNumber$1 as InputNumber, InteractiveGraph$1 as InteractiveGraphWidget, ItemExtras, JiptParagraphs, KhanColors, KhanMath, context as LoadingContext, Log, Matrix$1 as MatrixWidget, MultiItems, NumericInput$1 as NumericInput, PerseusExpressionAnswerFormConsidered, PerseusI18nContext, PerseusI18nContextProvider, PerseusMarkdown, Plotter$1 as PlotterWidget, QUESTION_WIDGETS, Radio, Renderer, ref as ServerItemRenderer, sizingUtils as SizingUtils, Table$1 as TableWidget, Util, denylist as WIDGET_PROP_DENYLIST, WidgetJsonifyDeprecated, widgets$1 as Widgets, addWidget, apiVersion, buildEmptyItemTreeForShape, buildMapper, components, constants, contentHasWidgetType, convertWidgetNameToEnum, displaySigFigs, generateTestCategorizerWidget, generateTestExpressionWidget, generateTestInteractiveGraphWidget, generateTestNumericInputWidget, generateTestPerseusItem, generateTestRadioWidget, genericPerseusItemData, getAnswerFromUserInput, getAnswersFromWidgets, getCorrectAnswerForWidgetId, getLineCoords, getLinearSystemCoords, getSegmentCoords, getValidWidgetIds, getWidgetFromWidgetMap, getWidgetIdsFromContent, getWidgetIdsFromContentByType, getWidgetTypeByWidgetId, getWidgetsFromWidgetMap, getWidgetsMapFromItemData, globalConstants, globalStyles, iconPaths as icons, init, injectWidgets, interactiveSizes$1 as interactiveSizes, isItemRenderableByVersion, isWidgetIdInContent, isWrongAnswerSupported, itemDataVersion, itemToTree, ItemVersion as itemVersion, libVersion, lockedFigureColors, lockedFigureFillStyles, mediaQueries, parsePerseusItem, plotterPlotTypes, preprocessTex, registerAllWidgetsForTesting, shapes, shouldHaveIndividualAnswer, traverse, usePerseusI18n, violatingWidgets, allWidgets as widgets };
|
|
47974
47673
|
//# sourceMappingURL=index.js.map
|