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
@@ -41,7 +41,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
41
41
|
UI.resizableDialog('sensitivity', 'SENSITIVITY_ANALYSIS');
|
42
42
|
this.close_btn = document.getElementById('sensitivity-close-btn');
|
43
43
|
this.close_btn.addEventListener('click', (e) => UI.toggleDialog(e));
|
44
|
-
// Control panel accepts drag/drop of entities
|
44
|
+
// Control panel accepts drag/drop of entities.
|
45
45
|
this.control_panel = document.getElementById('sensitivity-control-panel');
|
46
46
|
this.control_panel.addEventListener(
|
47
47
|
'dragover', (event) => SENSITIVITY_ANALYSIS.dragOver(event));
|
@@ -61,12 +61,12 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
61
61
|
this.delta.addEventListener(
|
62
62
|
'blur', () => SENSITIVITY_ANALYSIS.setDelta());
|
63
63
|
|
64
|
-
// NOTE:
|
64
|
+
// NOTE: Both the base selectors and the delta input blur on Enter.
|
65
65
|
const blurf = (event) => { if(event.key === 'Enter') event.target.blur(); };
|
66
66
|
this.base_selectors.addEventListener('keyup', blurf);
|
67
67
|
this.delta.addEventListener('keyup', blurf);
|
68
68
|
|
69
|
-
// Make parameter buttons responsive
|
69
|
+
// Make parameter buttons responsive.
|
70
70
|
document.getElementById('sa-p-add-btn').addEventListener(
|
71
71
|
'click', () => SENSITIVITY_ANALYSIS.promptForParameter());
|
72
72
|
document.getElementById('sa-p-up-btn').addEventListener(
|
@@ -75,7 +75,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
75
75
|
'click', () => SENSITIVITY_ANALYSIS.moveParameter(1));
|
76
76
|
document.getElementById('sa-p-delete-btn').addEventListener(
|
77
77
|
'click', () => SENSITIVITY_ANALYSIS.deleteParameter());
|
78
|
-
// Make outcome buttons responsive
|
78
|
+
// Make outcome buttons responsive.
|
79
79
|
document.getElementById('sa-o-add-btn').addEventListener(
|
80
80
|
'click', () => SENSITIVITY_ANALYSIS.promptForOutcome());
|
81
81
|
document.getElementById('sa-o-up-btn').addEventListener(
|
@@ -84,12 +84,12 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
84
84
|
'click', () => SENSITIVITY_ANALYSIS.moveOutcome(1));
|
85
85
|
document.getElementById('sa-o-delete-btn').addEventListener(
|
86
86
|
'click', () => SENSITIVITY_ANALYSIS.deleteOutcome());
|
87
|
-
// The toggle button to hide/show the control panel
|
87
|
+
// The toggle button to hide/show the control panel.
|
88
88
|
this.toggle_chevron = document.getElementById('sa-toggle-chevron');
|
89
89
|
this.toggle_chevron.addEventListener(
|
90
90
|
'click', () => SENSITIVITY_ANALYSIS.toggleControlPanel());
|
91
91
|
|
92
|
-
// The display panel and its buttons
|
92
|
+
// The display panel and its buttons.
|
93
93
|
this.display_panel = document.getElementById('sensitivity-display-panel');
|
94
94
|
this.start_btn = document.getElementById('sa-start-btn');
|
95
95
|
this.start_btn.addEventListener(
|
@@ -107,12 +107,12 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
107
107
|
this.statistic = document.getElementById('sensitivity-statistic');
|
108
108
|
this.statistic.addEventListener(
|
109
109
|
'change', () => SENSITIVITY_ANALYSIS.setStatistic());
|
110
|
-
// Scroll area for the outcomes table
|
110
|
+
// Scroll area for the outcomes table.
|
111
111
|
this.scroll_area = document.getElementById('sa-scroll-area');
|
112
112
|
this.scroll_area.addEventListener(
|
113
113
|
'mouseover', (event) => SENSITIVITY_ANALYSIS.showOutcome(event, ''));
|
114
114
|
this.table = document.getElementById('sa-table');
|
115
|
-
// Buttons at panel bottom
|
115
|
+
// Buttons at panel bottom.
|
116
116
|
this.abs_rel_btn = document.getElementById('sa-abs-rel');
|
117
117
|
this.abs_rel_btn.addEventListener(
|
118
118
|
'click', () => SENSITIVITY_ANALYSIS.toggleAbsoluteRelative());
|
@@ -129,19 +129,19 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
129
129
|
'click', () => SENSITIVITY_ANALYSIS.copyDataToClipboard());
|
130
130
|
this.outcome_name = document.getElementById('sa-outcome-name');
|
131
131
|
|
132
|
-
// The add variable modal
|
132
|
+
// The add variable modal.
|
133
133
|
this.variable_modal = new ModalDialog('add-sa-variable');
|
134
134
|
this.variable_modal.ok.addEventListener(
|
135
135
|
'click', () => SENSITIVITY_ANALYSIS.addVariable());
|
136
136
|
this.variable_modal.cancel.addEventListener(
|
137
137
|
'click', () => SENSITIVITY_ANALYSIS.variable_modal.hide());
|
138
|
-
// NOTE:
|
138
|
+
// NOTE: The modal calls methods of the Expression Editor dialog.
|
139
139
|
this.variable_modal.element('obj').addEventListener(
|
140
140
|
'change', () => X_EDIT.updateVariableBar('add-sa-'));
|
141
141
|
this.variable_modal.element('name').addEventListener(
|
142
142
|
'change', () => X_EDIT.updateAttributeSelector('add-sa-'));
|
143
143
|
|
144
|
-
// Initialize main dialog properties
|
144
|
+
// Initialize main dialog properties.
|
145
145
|
this.reset();
|
146
146
|
}
|
147
147
|
|
@@ -152,8 +152,8 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
152
152
|
}
|
153
153
|
|
154
154
|
updateControlPanel() {
|
155
|
-
//
|
156
|
-
// legend to the outcomes (also to prevent changes to parameters)
|
155
|
+
// Show the control panel, or when the analysis is running the
|
156
|
+
// legend to the outcomes (also to prevent changes to parameters).
|
157
157
|
this.base_selectors.value = MODEL.base_case_selectors;
|
158
158
|
this.delta.value = VM.sig4Dig(MODEL.sensitivity_delta);
|
159
159
|
const tr = [];
|
@@ -182,7 +182,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
182
182
|
document.getElementById('sa-o-table').innerHTML = tr.join('');
|
183
183
|
this.updateControlButtons('p');
|
184
184
|
this.updateControlButtons('o');
|
185
|
-
// NOTE:
|
185
|
+
// NOTE: Allow run without parameters, but not without outcomes.
|
186
186
|
if(MODEL.sensitivity_outcomes.length > 0) {
|
187
187
|
this.start_btn.classList.remove('disab');
|
188
188
|
this.start_btn.classList.add('enab');
|
@@ -190,7 +190,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
190
190
|
this.start_btn.classList.remove('enab');
|
191
191
|
this.start_btn.classList.add('disab');
|
192
192
|
}
|
193
|
-
// Show the "clear results" button only when selected experiment has run
|
193
|
+
// Show the "clear results" button only when selected experiment has run.
|
194
194
|
if(MODEL.sensitivity_runs.length > 0) {
|
195
195
|
this.reset_btn.classList.remove('off');
|
196
196
|
} else {
|
@@ -199,7 +199,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
199
199
|
}
|
200
200
|
this.variable_modal.element('obj').value = 0;
|
201
201
|
// Update variable dropdown list of the "add SA variable" modal using
|
202
|
-
// a method of the Expression Editor dialog
|
202
|
+
// a method of the Expression Editor dialog.
|
203
203
|
X_EDIT.updateVariableBar('add-sa-');
|
204
204
|
}
|
205
205
|
|
@@ -245,35 +245,32 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
245
245
|
}
|
246
246
|
|
247
247
|
showSelectorInfo(shift) {
|
248
|
-
// Called when cursor is moved over the base selectors input field
|
248
|
+
// Called when cursor is moved over the base selectors input field.
|
249
249
|
if(shift && MODEL.base_case_selectors.length > 0) {
|
250
250
|
// When selector(s) are specified and shift is pressed, show info on
|
251
|
-
// what the selectors constitute as base scenario
|
251
|
+
// what the selectors constitute as base scenario.
|
252
252
|
this.showBaseCaseInfo();
|
253
253
|
return;
|
254
254
|
}
|
255
|
-
// Otherwise, display list of all dataset selectors in docu-viewer
|
255
|
+
// Otherwise, display list of all dataset selectors in docu-viewer.
|
256
256
|
if(DOCUMENTATION_MANAGER.visible) {
|
257
257
|
const
|
258
258
|
ds_dict = MODEL.listOfAllSelectors,
|
259
259
|
html = [],
|
260
260
|
sl = Object.keys(ds_dict).sort((a, b) => UI.compareFullNames(a, b, true));
|
261
|
-
for(
|
261
|
+
for(const s of sl) {
|
262
262
|
const
|
263
|
-
s = sl[i],
|
264
263
|
dl = ds_dict[s],
|
265
264
|
dnl = [],
|
266
265
|
bs = (dl.length > 1 ?
|
267
266
|
' style="border: 0.5px solid #a080c0; border-right: none"' : '');
|
268
|
-
for(
|
269
|
-
dnl.push(dl[j].displayName);
|
270
|
-
}
|
267
|
+
for(const d of dl) dnl.push(d.displayName);
|
271
268
|
html.push('<tr><td class="sa-ds-sel" ',
|
272
269
|
'onclick="SENSITIVITY_ANALYSIS.toggleSelector(this);">',
|
273
270
|
s, '</td><td', bs, '>', dnl.join('<br>'), '</td></tr>');
|
274
271
|
}
|
275
272
|
if(html.length > 0) {
|
276
|
-
// Display information as read-only HTML
|
273
|
+
// Display information as read-only HTML.
|
277
274
|
DOCUMENTATION_MANAGER.title.innerText = 'Dataset selectors';
|
278
275
|
DOCUMENTATION_MANAGER.viewer.innerHTML =
|
279
276
|
'<table><tr><td><strong>Selector</strong></td>' +
|
@@ -287,7 +284,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
287
284
|
|
288
285
|
showBaseCaseInfo() {
|
289
286
|
// Display information on the base case selectors combination if docu-viewer
|
290
|
-
// is visible and cursor is moved over base case input field
|
287
|
+
// is visible and cursor is moved over base case input field.
|
291
288
|
const combi = MODEL.base_case_selectors.split(' ');
|
292
289
|
if(combi.length > 0 && DOCUMENTATION_MANAGER.visible) {
|
293
290
|
const
|
@@ -298,7 +295,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
298
295
|
for(let i = 0; i < combi.length; i++) {
|
299
296
|
const sel = combi[i];
|
300
297
|
html.push('<h3>Selector <tt>', sel, '</tt></h3>');
|
301
|
-
// List associated datasets (if any)
|
298
|
+
// List associated datasets (if any).
|
302
299
|
list.length = 0;
|
303
300
|
for(let id in MODEL.datasets) if(MODEL.datasets.hasOwnProperty(id)) {
|
304
301
|
const ds = MODEL.datasets[id];
|
@@ -315,7 +312,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
315
312
|
html.push('<em>Datasets:</em> <ul>', list.join(''), '</ul>');
|
316
313
|
}
|
317
314
|
info.html = html.join('');
|
318
|
-
// Display information as read-only HTML
|
315
|
+
// Display information as read-only HTML.
|
319
316
|
DOCUMENTATION_MANAGER.title.innerHTML = info.title;
|
320
317
|
DOCUMENTATION_MANAGER.viewer.innerHTML = info.html;
|
321
318
|
DOCUMENTATION_MANAGER.edit_btn.classList.remove('enab');
|
@@ -339,21 +336,19 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
339
336
|
}
|
340
337
|
|
341
338
|
editBaseSelectors() {
|
342
|
-
// Give visual feedback by setting background color to white
|
339
|
+
// Give visual feedback by setting background color to white.
|
343
340
|
this.base_selectors.style.backgroundColor = 'white';
|
344
341
|
}
|
345
342
|
|
346
343
|
setBaseSelectors() {
|
347
|
-
// Sanitize string before accepting it as space-separated selector list
|
344
|
+
// Sanitize string before accepting it as space-separated selector list.
|
348
345
|
const
|
349
346
|
sl = this.base_selectors.value.replace(/[\;\,]/g, ' ').trim().replace(
|
350
347
|
/[^a-zA-Z0-9\+\-\%\_\s]/g, '').split(/\s+/),
|
351
348
|
bs = sl.join(' '),
|
352
349
|
sd = MODEL.listOfAllSelectors,
|
353
350
|
us = [];
|
354
|
-
for(
|
355
|
-
if(sl[i].length > 0 && !(sl[i] in sd)) us.push(sl[i]);
|
356
|
-
}
|
351
|
+
for(const s of sl) if(s.length > 0 && !(s in sd)) us.push(s);
|
357
352
|
if(us.length > 0) {
|
358
353
|
UI.warn('Base contains ' + pluralS(us.length, 'unknown selector') +
|
359
354
|
': "' + us.join('", "') + '"');
|
@@ -367,7 +362,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
367
362
|
}
|
368
363
|
|
369
364
|
editDelta() {
|
370
|
-
// Give visual feedback by setting background color to white
|
365
|
+
// Give visual feedback by setting background color to white.
|
371
366
|
this.delta.backgroundColor = 'white';
|
372
367
|
}
|
373
368
|
|
@@ -438,24 +433,24 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
438
433
|
}
|
439
434
|
|
440
435
|
promptForParameter() {
|
441
|
-
// Open dialog for adding new parameter
|
436
|
+
// Open dialog for adding new parameter.
|
442
437
|
const md = this.variable_modal;
|
443
438
|
md.element('type').innerText = 'parameter';
|
444
|
-
// NOTE:
|
439
|
+
// NOTE: Clusters have no suitable attributes, and equations are endogenous.
|
445
440
|
md.element('cluster').style.display = 'none';
|
446
441
|
md.element('equation').style.display = 'none';
|
447
|
-
// NOTE:
|
442
|
+
// NOTE: Update to ensure that valid attributes are selectable.
|
448
443
|
X_EDIT.updateVariableBar('add-sa-');
|
449
444
|
md.show();
|
450
445
|
}
|
451
446
|
|
452
447
|
promptForOutcome() {
|
453
|
-
// Open dialog for adding new outcome
|
448
|
+
// Open dialog for adding new outcome.
|
454
449
|
const md = this.variable_modal;
|
455
450
|
md.element('type').innerText = 'outcome';
|
456
451
|
md.element('cluster').style.display = 'block';
|
457
452
|
md.element('equation').style.display = 'block';
|
458
|
-
// NOTE:
|
453
|
+
// NOTE: Update to ensure that valid attributes are selectable.
|
459
454
|
X_EDIT.updateVariableBar('add-sa-');
|
460
455
|
md.show();
|
461
456
|
}
|
@@ -470,7 +465,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
470
465
|
}
|
471
466
|
|
472
467
|
handleDrop(ev) {
|
473
|
-
// Prompt for attribute if dropped object is a suitable entity
|
468
|
+
// Prompt for attribute if dropped object is a suitable entity.
|
474
469
|
ev.preventDefault();
|
475
470
|
const
|
476
471
|
tid = ev.target.id,
|
@@ -510,13 +505,13 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
510
505
|
}
|
511
506
|
}
|
512
507
|
s.value = i;
|
513
|
-
// NOTE:
|
508
|
+
// NOTE: Use method of the Expression Editor, specifying the SA prefix.
|
514
509
|
X_EDIT.updateAttributeSelector('add-sa-');
|
515
510
|
}
|
516
511
|
}
|
517
512
|
|
518
513
|
addVariable() {
|
519
|
-
// Add parameter or outcome to the respective list
|
514
|
+
// Add parameter or outcome to the respective list.
|
520
515
|
const
|
521
516
|
md = this.variable_modal,
|
522
517
|
t = md.element('type').innerText,
|
@@ -525,13 +520,13 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
525
520
|
a = md.selectedOption('attr').text;
|
526
521
|
let n = '';
|
527
522
|
if(e === 'Equation' && a) {
|
528
|
-
// For equations, the attribute denotes the name
|
523
|
+
// For equations, the attribute denotes the name.
|
529
524
|
n = a;
|
530
525
|
} else if(o && a) {
|
531
526
|
// Most variables are defined by name + attribute ...
|
532
527
|
n = o + UI.OA_SEPARATOR + a;
|
533
528
|
} else if(e === 'Dataset' && o) {
|
534
|
-
// ... but for datasets the selector is optional
|
529
|
+
// ... but for datasets the selector is optional.
|
535
530
|
n = o;
|
536
531
|
}
|
537
532
|
if(n) {
|
@@ -546,21 +541,21 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
546
541
|
}
|
547
542
|
|
548
543
|
deleteParameter() {
|
549
|
-
// Remove selected parameter from the analysis
|
544
|
+
// Remove selected parameter from the analysis.
|
550
545
|
MODEL.sensitivity_parameters.splice(this.selected_parameter, 1);
|
551
546
|
this.selected_parameter = -1;
|
552
547
|
this.updateDialog();
|
553
548
|
}
|
554
549
|
|
555
550
|
deleteOutcome() {
|
556
|
-
// Remove selected outcome from the analysis
|
551
|
+
// Remove selected outcome from the analysis.
|
557
552
|
MODEL.sensitivity_outcomes.splice(this.selected_outcome, 1);
|
558
553
|
this.selected_outcome = -1;
|
559
554
|
this.updateDialog();
|
560
555
|
}
|
561
556
|
|
562
557
|
pause() {
|
563
|
-
// Interrupt solver but retain data on server and allow resume
|
558
|
+
// Interrupt solver but retain data on server and allow resume.
|
564
559
|
UI.notify('Run sequence will be suspended after the current run');
|
565
560
|
this.pause_btn.classList.add('blink');
|
566
561
|
this.stop_btn.classList.remove('off');
|
@@ -568,7 +563,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
568
563
|
}
|
569
564
|
|
570
565
|
resumeButtons() {
|
571
|
-
//
|
566
|
+
// Change buttons to "running" state, and return TRUE if state was "paused".
|
572
567
|
const paused = this.start_btn.classList.contains('blink');
|
573
568
|
this.start_btn.classList.remove('blink');
|
574
569
|
this.start_btn.classList.add('off');
|
@@ -579,7 +574,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
579
574
|
}
|
580
575
|
|
581
576
|
readyButtons() {
|
582
|
-
//
|
577
|
+
// Set experiment run control buttons in "ready" state.
|
583
578
|
this.pause_btn.classList.add('off');
|
584
579
|
this.stop_btn.classList.add('off');
|
585
580
|
this.start_btn.classList.remove('off', 'blink');
|
@@ -587,17 +582,17 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
587
582
|
}
|
588
583
|
|
589
584
|
pausedButtons(aci) {
|
590
|
-
//
|
585
|
+
// Set experiment run control buttons in "paused" state.
|
591
586
|
this.pause_btn.classList.remove('blink');
|
592
587
|
this.pause_btn.classList.add('off');
|
593
588
|
this.start_btn.classList.remove('off');
|
594
|
-
// Blinking start button indicates: paused -- click to resume
|
589
|
+
// Blinking start button indicates: paused -- click to resume.
|
595
590
|
this.start_btn.classList.add('blink');
|
596
591
|
this.progress.innerHTML = `Run ${aci} PAUSED`;
|
597
592
|
}
|
598
593
|
|
599
594
|
clearResults() {
|
600
|
-
//
|
595
|
+
// Clear results, and resets control buttons.
|
601
596
|
MODEL.sensitivity_runs.length = 0;
|
602
597
|
this.readyButtons();
|
603
598
|
this.reset_btn.classList.add('off');
|
@@ -608,18 +603,18 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
608
603
|
}
|
609
604
|
|
610
605
|
setProgress(msg) {
|
611
|
-
//
|
606
|
+
// Show `msg` in the progress field of the dialog.
|
612
607
|
this.progress.innerHTML = msg;
|
613
608
|
}
|
614
609
|
|
615
610
|
showCheckmark(t) {
|
616
|
-
//
|
611
|
+
// Show green checkmark (with elapsed time `t` as title) in progress field.
|
617
612
|
this.progress.innerHTML =
|
618
613
|
`<span class="x-checked" title="${t}">✔</span>`;
|
619
614
|
}
|
620
615
|
|
621
616
|
drawTable() {
|
622
|
-
//
|
617
|
+
// Draw sensitivity analysis as table.
|
623
618
|
const
|
624
619
|
html = [],
|
625
620
|
pl = MODEL.sensitivity_parameters.length,
|
@@ -678,15 +673,15 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
678
673
|
}
|
679
674
|
|
680
675
|
updateData() {
|
681
|
-
//
|
676
|
+
// Fill table cells with their data value or status.
|
682
677
|
const
|
683
678
|
pl = MODEL.sensitivity_parameters.length,
|
684
679
|
ol = MODEL.sensitivity_outcomes.length,
|
685
680
|
rl = MODEL.sensitivity_runs.length;
|
686
681
|
if(ol === 0) return;
|
687
|
-
// NOTE: computeData is a parent class method
|
682
|
+
// NOTE: computeData is a parent class method.
|
688
683
|
this.computeData(this.selected_statistic);
|
689
|
-
// Draw per row (i) where i=0 is the base case
|
684
|
+
// Draw per row (i) where i=0 is the base case.
|
690
685
|
for(let i = 0; i <= pl; i ++) {
|
691
686
|
if(i < 1 || !this.checked_parameters[MODEL.sensitivity_parameters[i-1]]) {
|
692
687
|
for(let j = 0; j < ol; j++) {
|
@@ -706,7 +701,7 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
706
701
|
}
|
707
702
|
if(i > 0 && this.relative_scale) {
|
708
703
|
let p = this.perc[j][i - 1];
|
709
|
-
// Replace warning sign by dash
|
704
|
+
// Replace warning sign by dash.
|
710
705
|
if(p === '\u26A0') p = '-';
|
711
706
|
c.innerText = p + (p !== '-' ? '%' : '');
|
712
707
|
} else {
|
@@ -720,16 +715,15 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
720
715
|
}
|
721
716
|
|
722
717
|
showOutcome(event, o) {
|
723
|
-
//
|
718
|
+
// Display outcome `o` (the name of the variable) below the table.
|
724
719
|
event.stopPropagation();
|
725
720
|
this.outcome_name.innerHTML = o;
|
726
721
|
}
|
727
722
|
|
728
723
|
selectRun(n) {
|
729
|
-
//
|
730
|
-
const
|
731
|
-
|
732
|
-
rows.item(i).classList.remove('sa-p-sel');
|
724
|
+
// Select run `n`, or toggles if already selected.
|
725
|
+
for(const row of this.scroll_area.getElementsByClassName('sa-p-sel')) {
|
726
|
+
row.classList.remove('sa-p-sel');
|
733
727
|
}
|
734
728
|
if(n === this.selected_run) {
|
735
729
|
this.selected_run = -1;
|
@@ -742,20 +736,20 @@ class GUISensitivityAnalysis extends SensitivityAnalysis {
|
|
742
736
|
}
|
743
737
|
|
744
738
|
setStatistic() {
|
745
|
-
// Update view for selected variable
|
739
|
+
// Update view for selected variable.
|
746
740
|
this.selected_statistic = this.statistic.value;
|
747
741
|
this.updateData();
|
748
742
|
}
|
749
743
|
|
750
744
|
toggleAbsoluteRelative() {
|
751
|
-
//
|
745
|
+
// Toggle between # (absolute) and % (relative) display of outcome values.
|
752
746
|
this.relative_scale = !this.relative_scale;
|
753
747
|
this.abs_rel_btn.innerText = (this.relative_scale ? '%' : '#');
|
754
748
|
this.updateData();
|
755
749
|
}
|
756
750
|
|
757
751
|
setColorScale(event) {
|
758
|
-
//
|
752
|
+
// Infer clicked color scale button from event, and select it.
|
759
753
|
if(event) {
|
760
754
|
const cs = event.target.id.split('-')[1];
|
761
755
|
this.color_scale.set(cs);
|