linny-r 2.0.8 → 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.
Files changed (31) hide show
  1. package/README.md +3 -40
  2. package/package.json +1 -1
  3. package/server.js +19 -157
  4. package/static/index.html +58 -20
  5. package/static/linny-r.css +20 -16
  6. package/static/scripts/iro.min.js +7 -7
  7. package/static/scripts/linny-r-ctrl.js +50 -72
  8. package/static/scripts/linny-r-gui-actor-manager.js +23 -33
  9. package/static/scripts/linny-r-gui-chart-manager.js +43 -41
  10. package/static/scripts/linny-r-gui-constraint-editor.js +6 -10
  11. package/static/scripts/linny-r-gui-controller.js +254 -230
  12. package/static/scripts/linny-r-gui-dataset-manager.js +17 -36
  13. package/static/scripts/linny-r-gui-documentation-manager.js +11 -17
  14. package/static/scripts/linny-r-gui-equation-manager.js +22 -22
  15. package/static/scripts/linny-r-gui-experiment-manager.js +102 -129
  16. package/static/scripts/linny-r-gui-file-manager.js +42 -48
  17. package/static/scripts/linny-r-gui-finder.js +105 -51
  18. package/static/scripts/linny-r-gui-model-autosaver.js +2 -4
  19. package/static/scripts/linny-r-gui-monitor.js +35 -41
  20. package/static/scripts/linny-r-gui-paper.js +42 -70
  21. package/static/scripts/linny-r-gui-power-grid-manager.js +31 -34
  22. package/static/scripts/linny-r-gui-receiver.js +1 -2
  23. package/static/scripts/linny-r-gui-repository-browser.js +44 -46
  24. package/static/scripts/linny-r-gui-scale-unit-manager.js +32 -32
  25. package/static/scripts/linny-r-gui-sensitivity-analysis.js +61 -67
  26. package/static/scripts/linny-r-gui-undo-redo.js +94 -95
  27. package/static/scripts/linny-r-milp.js +20 -24
  28. package/static/scripts/linny-r-model.js +1832 -2248
  29. package/static/scripts/linny-r-utils.js +27 -27
  30. package/static/scripts/linny-r-vm.js +801 -905
  31. 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
- // Refreshes all dialog fields to display actual MODEL chart properties
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(let i = 0; i < this.legend_options.length; i++) {
374
- const opt = this.legend_options[i], val = opt.toLowerCase();
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(let i = 0; i < c.variables.length; i++) {
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(let i = 0; i < c.variables.length; i++) {
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) chart.addWildcardVariables(dsm, indices);
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(let i = 0; i < indices.length; i++) {
755
- tr.push('<tr><td class="v-box"><div id="wcv-box-', indices[i],
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('??', indices[i]),
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 && il) {
775
- for(let i = 0; i < il.length; i++) {
776
- if(UI.boxChecked('wcv-box-'+ il[i])) indices.push(il[i]);
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
- // Displays the SVG image for chart `c` (computed by this Chart object)
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
- // Shows the statistics on the chart variables.
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(let i = 0; i < vbl.length; i++) {
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,10 +1001,9 @@ class GUIChartManager extends ChartManager {
998
1001
  '<th>&mu;</th><th>&sigma;</th><th>&Sigma;</th>',
999
1002
  '<th>&ne;0</th><th>&#x26A0;</th></tr>');
1000
1003
  nr = 0;
1001
- for(let i = 0; i < vbl.length; i++) {
1002
- const v = vbl[i];
1004
+ for(const v of vbl) {
1003
1005
  if(v.visible) {
1004
- // NOTE: while still solving, display t-1 as N
1006
+ // NOTE: While still solving, display t-1 as N.
1005
1007
  const n = Math.max(0, v.N);
1006
1008
  html.push('<tr><td class="v-name">', v.displayName, '</td><td>', n,
1007
1009
  '</td><td title="', v.minimum.toPrecision(8), '">', data[nr][0],
@@ -1086,17 +1088,17 @@ class GUIChartManager extends ChartManager {
1086
1088
  }
1087
1089
  }
1088
1090
 
1089
- downloadChart() {
1090
- // 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.
1091
1093
  if(this.chart_index >= 0) {
1092
- FILE_MANAGER.pushOutSVG(MODEL.charts[this.chart_index].svg);
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
+ }
1093
1100
  }
1094
1101
  }
1095
-
1096
- renderChartAsPNG() {
1097
- window.localStorage.removeItem('png-url');
1098
- FILE_MANAGER.renderSVGAsPNG(MODEL.charts[this.chart_index].svg);
1099
- }
1100
1102
 
1101
1103
  drawChart() {
1102
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(let i = 0; i < c.bound_lines.length; i++) {
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(let i = 0; i < l.points.length; i++) {
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(let i = 0; i < l.points.length; i++) {
1088
+ for(const p of l.points) {
1093
1089
  const
1094
- px = l.points[i][0],
1095
- py = l.points[i][1];
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.