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.
- package/README.md +3 -40
- package/package.json +1 -1
- package/server.js +19 -157
- package/static/index.html +58 -20
- package/static/linny-r.css +20 -16
- package/static/scripts/iro.min.js +7 -7
- package/static/scripts/linny-r-ctrl.js +50 -72
- package/static/scripts/linny-r-gui-actor-manager.js +23 -33
- package/static/scripts/linny-r-gui-chart-manager.js +43 -41
- 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 +17 -36
- 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 +42 -48
- 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 +27 -27
- package/static/scripts/linny-r-vm.js +801 -905
- package/static/show-png.html +0 -113
@@ -207,10 +207,9 @@ class GUIDatasetManager extends DatasetManager {
|
|
207
207
|
}
|
208
208
|
|
209
209
|
hideCollapsedRows() {
|
210
|
-
// Hides all rows except top level and immediate children of expanded
|
211
|
-
for(
|
210
|
+
// Hides all rows except top level and immediate children of expanded.
|
211
|
+
for(const row of this.dataset_table.rows) {
|
212
212
|
const
|
213
|
-
row = this.dataset_table.rows[i],
|
214
213
|
// Get the first DIV in the first TD of this row
|
215
214
|
first_div = row.firstChild.firstElementChild,
|
216
215
|
btn = first_div.dataset.prefix === 'x';
|
@@ -274,10 +273,7 @@ class GUIDatasetManager extends DatasetManager {
|
|
274
273
|
pl.pop();
|
275
274
|
}
|
276
275
|
this.hideCollapsedRows();
|
277
|
-
for(
|
278
|
-
const r = this.dataset_table.rows[i];
|
279
|
-
if(r.dataset.prefix === lcp) return r;
|
280
|
-
}
|
276
|
+
for(const r of this.dataset_table.rows) if(r.dataset.prefix === lcp) return r;
|
281
277
|
return null;
|
282
278
|
}
|
283
279
|
|
@@ -328,8 +324,8 @@ class GUIDatasetManager extends DatasetManager {
|
|
328
324
|
names = [],
|
329
325
|
pref_names = {},
|
330
326
|
xids = [];
|
331
|
-
for(
|
332
|
-
const pref = UI.prefixesAndName(MODEL.datasets[
|
327
|
+
for(const dn of dnl) {
|
328
|
+
const pref = UI.prefixesAndName(MODEL.datasets[dn].name);
|
333
329
|
// NOTE: only the name part (so no prefixes at all) will be shown
|
334
330
|
names.push(pref.pop());
|
335
331
|
indent.push(pref.length);
|
@@ -851,8 +847,7 @@ class GUIDatasetManager extends DatasetManager {
|
|
851
847
|
// Update all chartvariables referencing this dataset + old selector.
|
852
848
|
const vl = MODEL.datasetVariables;
|
853
849
|
let cv_cnt = 0;
|
854
|
-
for(
|
855
|
-
const v = vl[i];
|
850
|
+
for(const v of vl) {
|
856
851
|
if(v.object === this.selected_dataset && v.attribute === oldm.selector) {
|
857
852
|
v.attribute = m.selector;
|
858
853
|
cv_cnt++;
|
@@ -949,16 +944,10 @@ class GUIDatasetManager extends DatasetManager {
|
|
949
944
|
return;
|
950
945
|
}
|
951
946
|
prefix += UI.PREFIXER;
|
952
|
-
const
|
953
|
-
|
954
|
-
pml = ds.inferPrefixableModifiers,
|
955
|
-
xl = MODEL.allExpressions,
|
956
|
-
vl = MODEL.datasetVariables,
|
957
|
-
nl = MODEL.notesWithTags;
|
958
|
-
for(let i = 0; i < pml.length; i++) {
|
947
|
+
const dsn = ds.displayName;
|
948
|
+
for(const m of ds.inferPrefixableModifiers) {
|
959
949
|
// Create prefixed dataset with correct default value
|
960
950
|
const
|
961
|
-
m = pml[i],
|
962
951
|
sel = m.selector,
|
963
952
|
newds = MODEL.addDataset(prefix + sel);
|
964
953
|
if(newds) {
|
@@ -976,17 +965,16 @@ class GUIDatasetManager extends DatasetManager {
|
|
976
965
|
const
|
977
966
|
from = dsn + UI.OA_SEPARATOR + sel,
|
978
967
|
to = newds.displayName;
|
979
|
-
for(
|
980
|
-
|
981
|
-
// NOTE: variable should match original dataset + selector
|
968
|
+
for(const v of MODEL.datasetVariables) {
|
969
|
+
// NOTE: variable should match original dataset + selector.
|
982
970
|
if(v.displayName === from) {
|
983
|
-
// Change to new dataset WITHOUT selector
|
971
|
+
// Change to new dataset WITHOUT selector.
|
984
972
|
v.object = newds;
|
985
973
|
v.attribute = '';
|
986
974
|
vcount++;
|
987
975
|
}
|
988
976
|
}
|
989
|
-
// Rename variable in the Sensitivity Analysis
|
977
|
+
// Rename variable in the Sensitivity Analysis.
|
990
978
|
for(let j = 0; j < MODEL.sensitivity_parameters.length; j++) {
|
991
979
|
if(MODEL.sensitivity_parameters[j] === from) {
|
992
980
|
MODEL.sensitivity_parameters[j] = to;
|
@@ -1008,10 +996,8 @@ class GUIDatasetManager extends DatasetManager {
|
|
1008
996
|
// Pattern ends at any character that is invalid for a
|
1009
997
|
// dataset modifier selector (unlike equation names)
|
1010
998
|
'\\s*[^a-zA-Z0-9\\+\\-\\%\\_]', 'gi');
|
1011
|
-
for(
|
1012
|
-
const
|
1013
|
-
x = xl[j],
|
1014
|
-
matches = x.text.match(re);
|
999
|
+
for(const x of MODEL.allExpressions) {
|
1000
|
+
const matches = x.text.match(re);
|
1015
1001
|
if(matches) {
|
1016
1002
|
for(let k = 0; k < matches.length; k++) {
|
1017
1003
|
// NOTE: each match will start with the opening bracket,
|
@@ -1025,10 +1011,8 @@ class GUIDatasetManager extends DatasetManager {
|
|
1025
1011
|
x.code = null;
|
1026
1012
|
}
|
1027
1013
|
}
|
1028
|
-
for(
|
1029
|
-
const
|
1030
|
-
n = nl[j],
|
1031
|
-
matches = n.contents.match(re);
|
1014
|
+
for(const n of MODEL.notesWithTags) {
|
1015
|
+
const matches = n.contents.match(re);
|
1032
1016
|
if(matches) {
|
1033
1017
|
for(let k = 0; k < matches.length; k++) {
|
1034
1018
|
// See NOTE above for the use of `slice` here
|
@@ -1181,9 +1165,8 @@ class GUIDatasetManager extends DatasetManager {
|
|
1181
1165
|
parts = lines[0].split(sep),
|
1182
1166
|
dsn = [];
|
1183
1167
|
let quoted = false;
|
1184
|
-
for(
|
1168
|
+
for(const p of parts) {
|
1185
1169
|
const
|
1186
|
-
p = parts[i],
|
1187
1170
|
swq = /^\"(\"\")*($|[^\"])/.test(p),
|
1188
1171
|
ewq = p.endsWith('"');
|
1189
1172
|
if(!quoted && swq && !ewq) {
|
@@ -1236,8 +1219,6 @@ class GUIDatasetManager extends DatasetManager {
|
|
1236
1219
|
if(sf === '' && v !== '') {
|
1237
1220
|
UI.warn(`Invalid numerical value "${v}" for <strong>${dsn[j]}</strong> on line ${i}`);
|
1238
1221
|
return false;
|
1239
|
-
} else {
|
1240
|
-
dsa[j].push(sf);
|
1241
1222
|
}
|
1242
1223
|
}
|
1243
1224
|
}
|
@@ -280,10 +280,10 @@ class DocumentationManager {
|
|
280
280
|
|
281
281
|
clearEntity(list) {
|
282
282
|
// To be called when entities are deleted
|
283
|
-
if(list.indexOf(this.entity) >= 0) {
|
283
|
+
if(list === true || list.indexOf(this.entity) >= 0) {
|
284
284
|
this.stopEditing();
|
285
285
|
this.entity = null;
|
286
|
-
this.title.innerHTML = '
|
286
|
+
this.title.innerHTML = 'About Linny-R';
|
287
287
|
this.viewer.innerHTML = this.about_linny_r;
|
288
288
|
}
|
289
289
|
}
|
@@ -540,18 +540,17 @@ class DocumentationManager {
|
|
540
540
|
|
541
541
|
showArrowLinks(arrow) {
|
542
542
|
// Show list of links represented by a composite arrow.
|
543
|
-
const
|
544
|
-
n = arrow.links.length,
|
545
|
-
msg = 'Arrow represents ' + pluralS(n, 'link');
|
543
|
+
const msg = 'Arrow represents ' + pluralS(arrow.links.length, 'link');
|
546
544
|
UI.setMessage(msg);
|
547
545
|
if(this.visible && !this.editing) {
|
548
546
|
// Set the dialog title.
|
549
547
|
this.title.innerHTML = msg;
|
550
548
|
// Show list.
|
551
549
|
const lis = [];
|
552
|
-
let
|
553
|
-
|
554
|
-
|
550
|
+
let dn,
|
551
|
+
c,
|
552
|
+
af;
|
553
|
+
for(const l of arrow.links) {
|
555
554
|
dn = l.displayName;
|
556
555
|
if(l.from_node instanceof Process) {
|
557
556
|
c = UI.color.produced;
|
@@ -600,9 +599,7 @@ class DocumentationManager {
|
|
600
599
|
this.title.innerHTML = msg;
|
601
600
|
// Show list.
|
602
601
|
const lis = [];
|
603
|
-
for(
|
604
|
-
lis.push(`<li>${iol[i].displayName}</li>`);
|
605
|
-
}
|
602
|
+
for(const io of iol) lis.push(`<li>${io.displayName}</li>`);
|
606
603
|
lis.sort(ciCompare);
|
607
604
|
this.viewer.innerHTML = `<ul>${lis.join('')}</ul>`;
|
608
605
|
}
|
@@ -714,9 +711,8 @@ class DocumentationManager {
|
|
714
711
|
this.differenceAsTable(d.settings));
|
715
712
|
if('units' in d) html.push('<h2>Units</h2>',
|
716
713
|
this.differenceAsTable(d.units));
|
717
|
-
for(
|
718
|
-
|
719
|
-
if(e in d) html.push('<h2>' + this.propertyName(e) + '</h2>',
|
714
|
+
for(const e of UI.MC.ENTITY_PROPS) if(e in d) {
|
715
|
+
html.push('<h2>' + this.propertyName(e) + '</h2>',
|
720
716
|
this.differenceAsTable(d[e]));
|
721
717
|
}
|
722
718
|
if('charts' in d) html.push('<h2><em>Charts</em></h2>',
|
@@ -759,9 +755,7 @@ class DocumentationManager {
|
|
759
755
|
const
|
760
756
|
html = ['<table>'],
|
761
757
|
keys = Object.keys(d).sort();
|
762
|
-
for(
|
763
|
-
html.push(this.differenceAsTableRow(d, keys[i]));
|
764
|
-
}
|
758
|
+
for(const k of keys) html.push(this.differenceAsTableRow(d, k));
|
765
759
|
html.push('</table>');
|
766
760
|
return html.join('\n');
|
767
761
|
}
|
@@ -148,7 +148,7 @@ class EquationManager {
|
|
148
148
|
}
|
149
149
|
|
150
150
|
updateDialog() {
|
151
|
-
// Updates equation list, highlighting selected equation (if any)
|
151
|
+
// Updates equation list, highlighting selected equation (if any).
|
152
152
|
const
|
153
153
|
ed = MODEL.equations_dataset,
|
154
154
|
ml = [],
|
@@ -160,34 +160,36 @@ class EquationManager {
|
|
160
160
|
this.outcome_btn.classList.add('not-selected');
|
161
161
|
}
|
162
162
|
let smid = 'eqmtr';
|
163
|
+
// NOTE> Selector list `msl` contains names, not IDs.
|
163
164
|
for(let i = 0; i < msl.length; i++) {
|
164
165
|
const
|
165
|
-
|
166
|
-
|
167
|
-
|
166
|
+
id = UI.nameToID(msl[i]),
|
167
|
+
m = ed.modifiers[id],
|
168
|
+
sel = safeDoubleQuotes(m.selector),
|
169
|
+
expr = m.expression,
|
170
|
+
wild = (sel.indexOf('??') >= 0),
|
171
|
+
method = sel.startsWith(':'),
|
168
172
|
multi = (this.multi_line ? '-multi' : ''),
|
169
|
-
issue = (
|
170
|
-
(
|
171
|
-
clk =
|
172
|
-
|
173
|
-
|
174
|
-
m.identifier + '\', event.shiftKey);"' : '');
|
173
|
+
issue = (expr.compile_issue ? ' compile-issue' :
|
174
|
+
(expr.compute_issue ? ' compute-issue' : '')),
|
175
|
+
clk = `" onclick="EQUATION_MANAGER.selectModifier(event, '${id}'`,
|
176
|
+
mover = (!method ? '' :
|
177
|
+
`onmouseover="EQUATION_MANAGER.showInfo('${id}', event.shiftKey);"`);
|
175
178
|
if(m === sm) smid += i;
|
176
179
|
ml.push(['<tr id="eqmtr', i, '" class="dataset-modif',
|
177
180
|
(m === sm ? ' sel-set' : ''),
|
178
181
|
'"><td class="equation-selector',
|
179
182
|
(method ? ' method' : ''),
|
180
183
|
// Display in gray when method cannot be applied.
|
181
|
-
(
|
182
|
-
(
|
184
|
+
(expr.noMethodObject ? ' no-object' : ''),
|
185
|
+
(expr.isStatic ? '' : ' it'), issue,
|
183
186
|
(wild ? ' wildcard' : ''), clk, ', false);"', mover, '>',
|
184
187
|
(m.outcome_equation ? '<span class="outcome"></span>' : ''),
|
185
|
-
(wild ? wildcardFormat(
|
188
|
+
(wild ? wildcardFormat(sel) : sel),
|
186
189
|
'</td><td class="equation-expression', multi, issue,
|
187
190
|
(issue ? '"title="' +
|
188
|
-
safeDoubleQuotes(
|
189
|
-
|
190
|
-
clk, ');">', m.expression.text, '</td></tr>'].join(''));
|
191
|
+
safeDoubleQuotes(expr.compile_issue || expr.compute_issue) : ''),
|
192
|
+
clk, ');">', expr.text, '</td></tr>'].join(''));
|
191
193
|
}
|
192
194
|
this.table.innerHTML = ml.join('');
|
193
195
|
this.scroll_area.style.display = 'block';
|
@@ -208,10 +210,10 @@ class EquationManager {
|
|
208
210
|
|
209
211
|
selectModifier(event, id, x=true) {
|
210
212
|
// Select modifier, or when Alt- or double-clicked, edit its expression
|
211
|
-
// or the equation name (= name of the modifier)
|
213
|
+
// or the equation name (= name of the modifier).
|
212
214
|
if(MODEL.equations_dataset) {
|
213
215
|
const
|
214
|
-
m = MODEL.equations_dataset.modifiers[
|
216
|
+
m = MODEL.equations_dataset.modifiers[id] || null,
|
215
217
|
edit = event.altKey || this.doubleClicked(m);
|
216
218
|
this.selected_modifier = m;
|
217
219
|
if(m && edit) {
|
@@ -327,10 +329,8 @@ class EquationManager {
|
|
327
329
|
}
|
328
330
|
// Update all chartvariables referencing this dataset + old selector
|
329
331
|
let cv_cnt = 0;
|
330
|
-
for(
|
331
|
-
const
|
332
|
-
for(let j = 0; j < c.variables.length; j++) {
|
333
|
-
const v = c.variables[j];
|
332
|
+
for(const c of MODEL.charts) {
|
333
|
+
for(const v of c.variables) {
|
334
334
|
if(v.object === MODEL.equations_dataset && v.attribute === olds) {
|
335
335
|
v.attribute = m.selector;
|
336
336
|
cv_cnt++;
|