linny-r 2.0.7 → 2.0.9
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/README.md +3 -40
- package/package.json +1 -1
- package/server.js +19 -157
- package/static/index.html +74 -21
- package/static/linny-r.css +22 -16
- package/static/scripts/iro.min.js +7 -7
- package/static/scripts/linny-r-ctrl.js +51 -72
- package/static/scripts/linny-r-gui-actor-manager.js +23 -33
- package/static/scripts/linny-r-gui-chart-manager.js +50 -45
- package/static/scripts/linny-r-gui-constraint-editor.js +6 -10
- package/static/scripts/linny-r-gui-controller.js +254 -230
- package/static/scripts/linny-r-gui-dataset-manager.js +143 -32
- package/static/scripts/linny-r-gui-documentation-manager.js +11 -17
- package/static/scripts/linny-r-gui-equation-manager.js +22 -22
- package/static/scripts/linny-r-gui-experiment-manager.js +102 -129
- package/static/scripts/linny-r-gui-file-manager.js +53 -46
- package/static/scripts/linny-r-gui-finder.js +105 -51
- package/static/scripts/linny-r-gui-model-autosaver.js +2 -4
- package/static/scripts/linny-r-gui-monitor.js +35 -41
- package/static/scripts/linny-r-gui-paper.js +42 -70
- package/static/scripts/linny-r-gui-power-grid-manager.js +31 -34
- package/static/scripts/linny-r-gui-receiver.js +1 -2
- package/static/scripts/linny-r-gui-repository-browser.js +44 -46
- package/static/scripts/linny-r-gui-scale-unit-manager.js +32 -32
- package/static/scripts/linny-r-gui-sensitivity-analysis.js +61 -67
- package/static/scripts/linny-r-gui-undo-redo.js +94 -95
- package/static/scripts/linny-r-milp.js +20 -24
- package/static/scripts/linny-r-model.js +1832 -2248
- package/static/scripts/linny-r-utils.js +35 -27
- package/static/scripts/linny-r-vm.js +807 -905
- package/static/show-png.html +0 -113
@@ -123,9 +123,7 @@ class GUIChartManager extends ChartManager {
|
|
123
123
|
document.getElementById('chart-copy-table-btn').addEventListener(
|
124
124
|
'click', () => CHART_MANAGER.copyTable());
|
125
125
|
document.getElementById('chart-save-btn').addEventListener(
|
126
|
-
'click', () => CHART_MANAGER.downloadChart());
|
127
|
-
document.getElementById('chart-render-btn').addEventListener(
|
128
|
-
'click', () => CHART_MANAGER.renderChartAsPNG());
|
126
|
+
'click', () => CHART_MANAGER.downloadChart(event.shiftKey));
|
129
127
|
document.getElementById('chart-widen-btn').addEventListener(
|
130
128
|
'click', () => CHART_MANAGER.stretchChart(1));
|
131
129
|
document.getElementById('chart-narrow-btn').addEventListener(
|
@@ -356,7 +354,7 @@ class GUIChartManager extends ChartManager {
|
|
356
354
|
}
|
357
355
|
|
358
356
|
updateDialog() {
|
359
|
-
//
|
357
|
+
// Refreshe all dialog fields to display actual MODEL chart properties.
|
360
358
|
this.updateSelector();
|
361
359
|
let c = null;
|
362
360
|
if(this.chart_index >= 0) {
|
@@ -370,8 +368,8 @@ class GUIChartManager extends ChartManager {
|
|
370
368
|
}
|
371
369
|
UI.setBox('chart-title', c.show_title);
|
372
370
|
const ol = [];
|
373
|
-
for(
|
374
|
-
const
|
371
|
+
for(const opt of this.legend_options) {
|
372
|
+
const val = opt.toLowerCase();
|
375
373
|
ol.push(['<option value="', val,
|
376
374
|
(c.legend_position === val ? '" selected="selected' : ''),
|
377
375
|
'">', opt, '</option>'].join(''));
|
@@ -427,14 +425,16 @@ class GUIChartManager extends ChartManager {
|
|
427
425
|
} else {
|
428
426
|
UI.disableButtons(d_btn);
|
429
427
|
}
|
430
|
-
// If the Edit variable dialog is showing, update its header
|
428
|
+
// If the Edit variable dialog is showing, update its header.
|
431
429
|
if(this.variable_index >= 0 && !UI.hidden('variable-dlg')) {
|
432
430
|
document.getElementById('variable-dlg-name').innerHTML =
|
433
431
|
c.variables[this.variable_index].displayName;
|
434
432
|
}
|
435
433
|
}
|
434
|
+
// Finder dialog may need to update its "add variables to chart" button
|
435
|
+
if(FINDER.visible) FINDER.updateDialog();
|
436
436
|
this.add_variable_modal.element('obj').value = 0;
|
437
|
-
// Update variable dropdown list of the "add variable" modal
|
437
|
+
// Update variable dropdown list of the "add variable" modal.
|
438
438
|
X_EDIT.updateVariableBar('add-');
|
439
439
|
this.stretchChart(0);
|
440
440
|
}
|
@@ -507,9 +507,7 @@ class GUIChartManager extends ChartManager {
|
|
507
507
|
let n = '';
|
508
508
|
if(c.histogram) {
|
509
509
|
let vv = [];
|
510
|
-
for(
|
511
|
-
if(c.variables[i].visible) vv.push(c.variables[i]);
|
512
|
-
}
|
510
|
+
for(const v of c.variables) if(v.visible) vv.push(v);
|
513
511
|
const
|
514
512
|
l = vv.length,
|
515
513
|
bars = c.bins * l,
|
@@ -608,10 +606,8 @@ class GUIChartManager extends ChartManager {
|
|
608
606
|
nc.bins = c.bins;
|
609
607
|
nc.show_title = c.show_title;
|
610
608
|
nc.legend_position = c.legend_position;
|
611
|
-
for(
|
612
|
-
const
|
613
|
-
cv = c.variables[i],
|
614
|
-
nv = new ChartVariable(nc);
|
609
|
+
for(const cv of c.variables) {
|
610
|
+
const nv = new ChartVariable(nc);
|
615
611
|
nv.setProperties(cv.object, cv.attribute, cv.stacked,
|
616
612
|
cv.color, cv.scale_factor, cv.line_width, cv.sorted);
|
617
613
|
nc.variables.push(nv);
|
@@ -743,7 +739,16 @@ class GUIChartManager extends ChartManager {
|
|
743
739
|
// First hide the "Add variable" modal.
|
744
740
|
this.add_variable_modal.hide();
|
745
741
|
// Do not prompt for selection if there is only 1 match.
|
746
|
-
if(indices.length < 2)
|
742
|
+
if(indices.length < 2) {
|
743
|
+
if(indices.length) {
|
744
|
+
chart.addWildcardVariables(dsm, indices);
|
745
|
+
} else if(dsm.selector.startsWith(':')) {
|
746
|
+
UI.notify('Plotting methods is work-in-progress!');
|
747
|
+
} else {
|
748
|
+
UI.notify(`Variable "${dsm.displayName}" cannot be plotted`);
|
749
|
+
}
|
750
|
+
return;
|
751
|
+
}
|
747
752
|
md.chart = chart;
|
748
753
|
md.modifier = dsm;
|
749
754
|
md.indices = indices;
|
@@ -751,10 +756,10 @@ class GUIChartManager extends ChartManager {
|
|
751
756
|
tr = [],
|
752
757
|
dn = dsm.displayName,
|
753
758
|
tbl = md.element('table');
|
754
|
-
for(
|
755
|
-
tr.push('<tr><td class="v-box"><div id="wcv-box-',
|
759
|
+
for(const index of indices) {
|
760
|
+
tr.push('<tr><td class="v-box"><div id="wcv-box-', index,
|
756
761
|
'" class="box clear" onclick="UI.toggleBox(event);"></td>',
|
757
|
-
'<td class="vname">', dn.replace('??',
|
762
|
+
'<td class="vname">', dn.replace('??', index),
|
758
763
|
'</td></tr>');
|
759
764
|
tbl.innerHTML = tr.join('');
|
760
765
|
}
|
@@ -769,11 +774,10 @@ class GUIChartManager extends ChartManager {
|
|
769
774
|
md = this.add_wildcard_modal,
|
770
775
|
c = md.chart,
|
771
776
|
dsm = md.modifier,
|
772
|
-
il = md.indices,
|
773
777
|
indices = [];
|
774
|
-
if(c && dsm
|
775
|
-
for(
|
776
|
-
if(UI.boxChecked('wcv-box-'+
|
778
|
+
if(c && dsm) {
|
779
|
+
for(const index of md.indices) {
|
780
|
+
if(UI.boxChecked('wcv-box-'+ index)) indices.push(index);
|
777
781
|
}
|
778
782
|
}
|
779
783
|
if(indices.length) c.addWildcardVariables(dsm, indices);
|
@@ -947,28 +951,27 @@ class GUIChartManager extends ChartManager {
|
|
947
951
|
this.variable_index = -1;
|
948
952
|
this.updateDialog();
|
949
953
|
// Also update the experiment viewer (charts define the output variables)
|
950
|
-
// and finder dialog
|
954
|
+
// and finder dialog.
|
951
955
|
if(EXPERIMENT_MANAGER.selected_experiment) UI.updateControllerDialogs('FX');
|
952
956
|
}
|
953
957
|
this.variable_modal.hide();
|
954
958
|
}
|
955
959
|
|
956
960
|
showChartImage(c) {
|
957
|
-
//
|
961
|
+
// Display the SVG image for chart `c` (computed by this Chart object).
|
958
962
|
if(c) document.getElementById('chart-svg').innerHTML = c.svg;
|
959
963
|
}
|
960
964
|
|
961
965
|
drawTable() {
|
962
|
-
//
|
966
|
+
// Show the statistics on the chart variables.
|
963
967
|
const html = [];
|
964
968
|
let vbl = [];
|
965
969
|
if(this.chart_index >= 0) vbl = MODEL.charts[this.chart_index].variables;
|
966
970
|
// First get the (potentially floating point) numbers so that their format
|
967
|
-
// can be made uniform per column
|
971
|
+
// can be made uniform per column.
|
968
972
|
const data = [];
|
969
973
|
let nr = 0;
|
970
|
-
for(
|
971
|
-
const v = vbl[i];
|
974
|
+
for(const v of vbl) {
|
972
975
|
if(v.visible) {
|
973
976
|
data.push([VM.sig4Dig(v.minimum), VM.sig4Dig(v.maximum),
|
974
977
|
VM.sig4Dig(v.mean), VM.sig4Dig(Math.sqrt(v.variance)),
|
@@ -980,7 +983,7 @@ class GUIChartManager extends ChartManager {
|
|
980
983
|
this.table_panel.innerHTML = '<div id="no-chart-data">No data</div>';
|
981
984
|
return;
|
982
985
|
}
|
983
|
-
// Process each of 5 columns separately
|
986
|
+
// Process each of 5 columns separately.
|
984
987
|
for(let c = 0; c < 5; c++) {
|
985
988
|
const col = [];
|
986
989
|
for(let r = 0; r < data.length; r++) {
|
@@ -998,15 +1001,17 @@ class GUIChartManager extends ChartManager {
|
|
998
1001
|
'<th>μ</th><th>σ</th><th>Σ</th>',
|
999
1002
|
'<th>≠0</th><th>⚠</th></tr>');
|
1000
1003
|
nr = 0;
|
1001
|
-
for(
|
1002
|
-
const v = vbl[i];
|
1004
|
+
for(const v of vbl) {
|
1003
1005
|
if(v.visible) {
|
1004
|
-
// NOTE:
|
1006
|
+
// NOTE: While still solving, display t-1 as N.
|
1005
1007
|
const n = Math.max(0, v.N);
|
1006
|
-
html.push('<tr><td class="v-name">',
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1008
|
+
html.push('<tr><td class="v-name">', v.displayName, '</td><td>', n,
|
1009
|
+
'</td><td title="', v.minimum.toPrecision(8), '">', data[nr][0],
|
1010
|
+
'</td><td title="', v.maximum.toPrecision(8), '">', data[nr][1],
|
1011
|
+
'</td><td title="', v.mean.toPrecision(8), '">', data[nr][2],
|
1012
|
+
'</td><td title="', Math.sqrt(v.variance).toPrecision(8), '">', data[nr][3],
|
1013
|
+
'</td><td title="', v.sum.toPrecision(8), '">', data[nr][4],
|
1014
|
+
'</td><td>', v.non_zero_tally, '</td><td>', v.exceptions,
|
1010
1015
|
'</td></tr>');
|
1011
1016
|
nr++;
|
1012
1017
|
}
|
@@ -1083,17 +1088,17 @@ class GUIChartManager extends ChartManager {
|
|
1083
1088
|
}
|
1084
1089
|
}
|
1085
1090
|
|
1086
|
-
downloadChart() {
|
1087
|
-
// Pushes the SVG of the selected chart as file to the browser
|
1091
|
+
downloadChart(shift) {
|
1092
|
+
// Pushes the SVG of the selected chart as file to the browser.
|
1088
1093
|
if(this.chart_index >= 0) {
|
1089
|
-
|
1094
|
+
const svg = MODEL.charts[this.chart_index].svg;
|
1095
|
+
if(shift) {
|
1096
|
+
FILE_MANAGER.pushOutSVG(svg);
|
1097
|
+
} else {
|
1098
|
+
FILE_MANAGER.pushOutPNG(svg);
|
1099
|
+
}
|
1090
1100
|
}
|
1091
1101
|
}
|
1092
|
-
|
1093
|
-
renderChartAsPNG() {
|
1094
|
-
window.localStorage.removeItem('png-url');
|
1095
|
-
FILE_MANAGER.renderSVGAsPNG(MODEL.charts[this.chart_index].svg);
|
1096
|
-
}
|
1097
1102
|
|
1098
1103
|
drawChart() {
|
1099
1104
|
// Displays the selected chart unless an experiment is running, or
|
@@ -984,11 +984,10 @@ class ConstraintEditor {
|
|
984
984
|
'</defs>'].join('');
|
985
985
|
// Draw the grid
|
986
986
|
this.drawGrid();
|
987
|
-
// Use c as shorthand for this.constraint
|
987
|
+
// Use `c` as shorthand for this.constraint.
|
988
988
|
const c = this.constraint;
|
989
989
|
// Add the SVG for lower and upper bounds
|
990
|
-
for(
|
991
|
-
const bl = c.bound_lines[i];
|
990
|
+
for(const bl of c.bound_lines) {
|
992
991
|
this.drawContour(bl);
|
993
992
|
this.drawLine(bl);
|
994
993
|
}
|
@@ -1057,10 +1056,7 @@ class ConstraintEditor {
|
|
1057
1056
|
} else {
|
1058
1057
|
const base_y = (l.type === VM.GE ? 0 : 100);
|
1059
1058
|
cp = 'M' + this.point(0, base_y);
|
1060
|
-
for(
|
1061
|
-
const p = l.points[i];
|
1062
|
-
cp += `L${this.point(p[0], p[1])}`;
|
1063
|
-
}
|
1059
|
+
for(const p of l.points) cp += `L${this.point(p[0], p[1])}`;
|
1064
1060
|
cp += 'L' + this.point(100, base_y) + 'z';
|
1065
1061
|
// Save the contour for rapid display of thumbnails.
|
1066
1062
|
l.contour_path = cp;
|
@@ -1089,10 +1085,10 @@ class ConstraintEditor {
|
|
1089
1085
|
const
|
1090
1086
|
cfs = `fill="${color}" stroke="${color}" stroke-width="${width}"`,
|
1091
1087
|
icfs = 'fill="white" stroke="white" stroke-width="1"';
|
1092
|
-
for(
|
1088
|
+
for(const p of l.points) {
|
1093
1089
|
const
|
1094
|
-
px =
|
1095
|
-
py =
|
1090
|
+
px = p[0],
|
1091
|
+
py = p[1];
|
1096
1092
|
pp.push(this.point(px, py));
|
1097
1093
|
dots += `<circle ${this.circleCenter(px, py)} r="3" ${cfs}></circle>`;
|
1098
1094
|
// Draw "custom points" with a white inner circle.
|