linny-r 2.0.9 → 2.0.10
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/package.json +6 -2
- package/static/images/solve-not-same-changed.png +0 -0
- package/static/images/solve-not-same-not-changed.png +0 -0
- package/static/images/solve-same-changed.png +0 -0
- package/static/images/solve-same-not-changed.png +0 -0
- package/static/index.html +79 -0
- package/static/linny-r.css +240 -7
- package/static/scripts/linny-r-ctrl.js +76 -13
- package/static/scripts/linny-r-gui-chart-manager.js +13 -12
- package/static/scripts/linny-r-gui-constraint-editor.js +4 -4
- package/static/scripts/linny-r-gui-controller.js +390 -30
- package/static/scripts/linny-r-gui-dataset-manager.js +48 -31
- package/static/scripts/linny-r-gui-experiment-manager.js +22 -12
- package/static/scripts/linny-r-gui-expression-editor.js +26 -12
- package/static/scripts/linny-r-gui-finder.js +190 -5
- package/static/scripts/linny-r-model.js +112 -38
- package/static/scripts/linny-r-vm.js +99 -93
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "linny-r",
|
3
|
-
"version": "2.0.
|
3
|
+
"version": "2.0.10",
|
4
4
|
"description": "Executable graphical language with WYSIWYG editor for MILP models",
|
5
5
|
"main": "server.js",
|
6
6
|
"scripts": {
|
@@ -21,7 +21,11 @@
|
|
21
21
|
"optimization",
|
22
22
|
"simulation",
|
23
23
|
"unit commitment",
|
24
|
-
"
|
24
|
+
"industrial ecology",
|
25
|
+
"linearized power flow",
|
26
|
+
"loss approximation",
|
27
|
+
"generation expansion",
|
28
|
+
"grid expansion"
|
25
29
|
],
|
26
30
|
"author": "Pieter W.G. Bots",
|
27
31
|
"license": "MIT",
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
package/static/index.html
CHANGED
@@ -1730,7 +1730,86 @@ Each line should represent the points of a different bound line.">
|
|
1730
1730
|
</div>
|
1731
1731
|
</div>
|
1732
1732
|
</div>
|
1733
|
+
|
1734
|
+
<!-- the DATASET GROUP modal allows editing properties of multiple datasets -->
|
1735
|
+
<div id="datasetgroup-modal" class="modal">
|
1736
|
+
<div id="datasetgroup-dlg" class="inp-dlg">
|
1737
|
+
<div class="dlg-title">
|
1738
|
+
Dataset group properties
|
1739
|
+
<span id="datasetgroup-group"></span>
|
1740
|
+
<img class="cancel-btn" src="images/cancel.png">
|
1741
|
+
<img class="ok-btn" src="images/ok.png">
|
1742
|
+
</div>
|
1743
|
+
<div id="datasetgroup-prefix-lbl">Prefix:</div>
|
1744
|
+
<input id="datasetgroup-prefix" type="text" autocomplete="off">
|
1745
|
+
<div id="datasetgroup-default-lbl">Default value:</div>
|
1746
|
+
<input id="datasetgroup-default" type="text" autocomplete="off">
|
1747
|
+
<div id="datasetgroup-unit-lbl">Unit:</div>
|
1748
|
+
<input id="datasetgroup-unit" type="text" list="units-data" autocomplete="off">
|
1749
|
+
<div id="datasetgroup-periodic" class="box clear"></div>
|
1750
|
+
<div id="datasetgroup-periodic-lbl">Periodic</div>
|
1751
|
+
<div id="datasetgroup-array" class="box clear"></div>
|
1752
|
+
<div id="datasetgroup-array-lbl">Array</div>
|
1753
|
+
<div id="datasetgroup-no-time-msg">
|
1754
|
+
Arrays ignore time dimension
|
1755
|
+
</div>
|
1756
|
+
<div id="datasetgroup-time-step-lbl">Time step:</div>
|
1757
|
+
<input id="datasetgroup-time-scale" type="text" autocomplete="off">
|
1758
|
+
<select id="datasetgroup-time-unit">
|
1759
|
+
<option value="year">yr</option>
|
1760
|
+
<option value="week">wk</option>
|
1761
|
+
<option value="day">d</option>
|
1762
|
+
<option value="hour">h</option>
|
1763
|
+
<option value="minute">m</option>
|
1764
|
+
<option value="second">s</option>
|
1765
|
+
</select>
|
1766
|
+
<div id="datasetgroup-method-lbl">Method:</div>
|
1767
|
+
<select id="datasetgroup-method">
|
1768
|
+
<option value="nearest">at nearest t</option>
|
1769
|
+
<option value="w-mean">weighted mean</option>
|
1770
|
+
<option value="w-sum">weighted sum</option>
|
1771
|
+
<option value="max">maximum</option>
|
1772
|
+
</select>
|
1773
|
+
<div id="datasetgroup-separator"></div>
|
1774
|
+
<div id="datasetgroup-modif-header">Modifiers</div>
|
1775
|
+
<div id="datasetgroup-modif-titles">
|
1776
|
+
<span>Selector</span>
|
1777
|
+
<span style="margin-left: 35px">Expression</span>
|
1778
|
+
</div>
|
1779
|
+
<div id="datasetgroup-modif-scroll-area">
|
1780
|
+
<table id="datasetgroup-modif-table">
|
1781
|
+
</table>
|
1782
|
+
</div>
|
1783
|
+
<div id="datasetgroup-modif-buttons">
|
1784
|
+
<img id="dsg-add-modif-btn" class="btn enab"
|
1785
|
+
src="images/add-selector.png" title="Add new selector">
|
1786
|
+
<img id="dsg-rename-modif-btn" class="btn disab" src="images/rename.png"
|
1787
|
+
title="Rename selected modifier">
|
1788
|
+
<img id="dsg-edit-modif-btn" class="btn disab"
|
1789
|
+
src="images/edit.png" title="Edit expression of selected modifier">
|
1790
|
+
<img id="dsg-delete-modif-btn" class="btn disab"
|
1791
|
+
src="images/delete.png" title="Delete selected modifier"
|
1792
|
+
style="margin-left: 20px">
|
1793
|
+
</div>
|
1794
|
+
</div>
|
1795
|
+
</div>
|
1733
1796
|
|
1797
|
+
<!-- the GROUP SELECTOR dialog prompts for a new selector -->
|
1798
|
+
<div id="group-selector-modal" class="modal">
|
1799
|
+
<div id="group-selector-dlg" class="inp-dlg">
|
1800
|
+
<div class="dlg-title">
|
1801
|
+
<span id="group-selector-action">Add</span> selector
|
1802
|
+
<img class="cancel-btn" src="images/cancel.png">
|
1803
|
+
<img class="ok-btn" src="images/ok.png">
|
1804
|
+
</div>
|
1805
|
+
<input id="group-selector-name" type="text"
|
1806
|
+
title="Can contain only alphanumeric characters, +, -, and %
|
1807
|
+
NOTE: * and ? will be interpreted as wildcards"
|
1808
|
+
maxlength="10" autocomplete="off">
|
1809
|
+
<div id="group-selector-label">(1 to 10 characters)</div>
|
1810
|
+
</div>
|
1811
|
+
</div>
|
1812
|
+
|
1734
1813
|
<!-- The CLONE dialog prompts for a prefix -->
|
1735
1814
|
<div id="clone-modal" class="modal">
|
1736
1815
|
<div id="clone-dlg" class="inp-dlg">
|
package/static/linny-r.css
CHANGED
@@ -396,6 +396,28 @@ input[type="text"]:disabled {
|
|
396
396
|
background-color: #f4f0f2;
|
397
397
|
}
|
398
398
|
|
399
|
+
td.same-not-changed {
|
400
|
+
color: #5060b0;
|
401
|
+
background-color: #f4f8ff;
|
402
|
+
}
|
403
|
+
|
404
|
+
td.not-same-not-changed {
|
405
|
+
color: #b06050;
|
406
|
+
background-color: #fff6f4;
|
407
|
+
}
|
408
|
+
|
409
|
+
td.same-changed {
|
410
|
+
color: #0000e0;
|
411
|
+
background-color: #f4f8ff;
|
412
|
+
text-shadow: 0px 0px 10px #00b0ff;
|
413
|
+
}
|
414
|
+
|
415
|
+
td.not-same-changed {
|
416
|
+
color: #e00000;
|
417
|
+
background-color: #fff6f4;
|
418
|
+
text-shadow: 0px 0px 10px #ff6000;
|
419
|
+
}
|
420
|
+
|
399
421
|
input[type="text"].same-not-changed {
|
400
422
|
color: #5060b0;
|
401
423
|
background-color: #f4f8ff;
|
@@ -426,10 +448,12 @@ select.not-same-not-changed {
|
|
426
448
|
|
427
449
|
select.same-changed {
|
428
450
|
color: #0000e0;
|
451
|
+
text-shadow: 0px 0px 10px #00b0ff;
|
429
452
|
}
|
430
453
|
|
431
454
|
select.not-same-changed {
|
432
455
|
color: #e00000;
|
456
|
+
text-shadow: 0px 0px 10px #ff6000;
|
433
457
|
}
|
434
458
|
|
435
459
|
textarea {
|
@@ -685,6 +709,7 @@ img.inline-cancel-btn:hover {
|
|
685
709
|
#actor-group,
|
686
710
|
#constraint-group,
|
687
711
|
#cluster-group,
|
712
|
+
#datasetgroup-group,
|
688
713
|
#link-group,
|
689
714
|
#process-group,
|
690
715
|
#product-group {
|
@@ -1910,6 +1935,7 @@ td.export {
|
|
1910
1935
|
|
1911
1936
|
#actor-export,
|
1912
1937
|
#dataset-export,
|
1938
|
+
#datasetgroup-export,
|
1913
1939
|
#product-export {
|
1914
1940
|
position: absolute;
|
1915
1941
|
bottom: 10px;
|
@@ -1921,6 +1947,7 @@ td.export {
|
|
1921
1947
|
|
1922
1948
|
#actor-import,
|
1923
1949
|
#dataset-import,
|
1950
|
+
#datasetgroup-import,
|
1924
1951
|
#product-import {
|
1925
1952
|
position: absolute;
|
1926
1953
|
bottom: 9px;
|
@@ -2607,6 +2634,7 @@ div.io-box {
|
|
2607
2634
|
#power-grids-table,
|
2608
2635
|
#dataset-table,
|
2609
2636
|
#dataset-modif-table,
|
2637
|
+
#datasetgroup-modif-table,
|
2610
2638
|
#equation-table,
|
2611
2639
|
#experiment-table,
|
2612
2640
|
#experiment-dim-table,
|
@@ -2647,6 +2675,7 @@ div.io-box {
|
|
2647
2675
|
}
|
2648
2676
|
|
2649
2677
|
#dataset-outcome.not-selected,
|
2678
|
+
#datasetgroup-outcome.not-selected,
|
2650
2679
|
#equation-outcome.not-selected {
|
2651
2680
|
filter: saturate(0) contrast(50%) brightness(170%);
|
2652
2681
|
}
|
@@ -2703,7 +2732,8 @@ div.io-box {
|
|
2703
2732
|
left: calc(40% + 3px);
|
2704
2733
|
}
|
2705
2734
|
|
2706
|
-
#dataset-modif-buttons > img.btn
|
2735
|
+
#dataset-modif-buttons > img.btn,
|
2736
|
+
#datasetgroup-modif-buttons > img.btn {
|
2707
2737
|
height: 20px;
|
2708
2738
|
width: 20px;
|
2709
2739
|
}
|
@@ -2729,6 +2759,11 @@ tr.sel-set {
|
|
2729
2759
|
background-color: #eff0ff;
|
2730
2760
|
}
|
2731
2761
|
|
2762
|
+
tr.sel-set > td,
|
2763
|
+
tr.dataset-modif:hover > td {
|
2764
|
+
background-color: inherit !important;
|
2765
|
+
}
|
2766
|
+
|
2732
2767
|
tr.def-sel {
|
2733
2768
|
color: #400090;
|
2734
2769
|
font-weight: bold;
|
@@ -2931,11 +2966,13 @@ td.equation-expression-multi {
|
|
2931
2966
|
color: #e0e0e0;
|
2932
2967
|
}
|
2933
2968
|
|
2934
|
-
#dataset-blackbox.off
|
2969
|
+
#dataset-blackbox.off,
|
2970
|
+
#datasetgroup-blackbox.off {
|
2935
2971
|
color: #e0e0e0;
|
2936
2972
|
}
|
2937
2973
|
|
2938
|
-
#dataset-blackbox.on
|
2974
|
+
#dataset-blackbox.on,
|
2975
|
+
#datasetgroup-blackbox.on {
|
2939
2976
|
color: #403848;
|
2940
2977
|
}
|
2941
2978
|
|
@@ -2999,18 +3036,21 @@ td.equation-expression-multi {
|
|
2999
3036
|
|
3000
3037
|
/* NOTE: New and Rename modals must be above boundline data modal */
|
3001
3038
|
#new-selector-modal,
|
3002
|
-
#rename-selector-modal
|
3039
|
+
#rename-selector-modal,
|
3040
|
+
#group-selector-modal {
|
3003
3041
|
z-index: 102;
|
3004
3042
|
}
|
3005
3043
|
|
3006
3044
|
#new-selector-dlg,
|
3007
|
-
#rename-selector-dlg
|
3045
|
+
#rename-selector-dlg,
|
3046
|
+
#group-selector-dlg {
|
3008
3047
|
width: 215px;
|
3009
3048
|
height: 45px;
|
3010
3049
|
}
|
3011
3050
|
|
3012
3051
|
#new-selector-name,
|
3013
|
-
#rename-selector-name
|
3052
|
+
#rename-selector-name,
|
3053
|
+
#group-selector-name {
|
3014
3054
|
position: absolute;
|
3015
3055
|
bottom: 2px;
|
3016
3056
|
left: 2px;
|
@@ -3018,7 +3058,8 @@ td.equation-expression-multi {
|
|
3018
3058
|
}
|
3019
3059
|
|
3020
3060
|
#new-selector-label,
|
3021
|
-
#rename-selector-label
|
3061
|
+
#rename-selector-label,
|
3062
|
+
#group-selector-label {
|
3022
3063
|
position: absolute;
|
3023
3064
|
left: 110px;
|
3024
3065
|
bottom: 5px;
|
@@ -5104,6 +5145,198 @@ img.finder {
|
|
5104
5145
|
font-size: 12px;
|
5105
5146
|
}
|
5106
5147
|
|
5148
|
+
/* the DATASET GROUP modal permits editing properties of multiple datasets */
|
5149
|
+
#datasetgroup-dlg {
|
5150
|
+
width: 440px;
|
5151
|
+
height: 190px;
|
5152
|
+
}
|
5153
|
+
|
5154
|
+
#datasetgroup-prefix-lbl {
|
5155
|
+
position: absolute;
|
5156
|
+
top: 25px;
|
5157
|
+
left: 2px;
|
5158
|
+
}
|
5159
|
+
|
5160
|
+
#datasetgroup-prefix {
|
5161
|
+
position: absolute;
|
5162
|
+
top: 24px;
|
5163
|
+
left: 38px;
|
5164
|
+
width: 121px;
|
5165
|
+
font-size: 12px;
|
5166
|
+
}
|
5167
|
+
|
5168
|
+
#datasetgroup-default-lbl {
|
5169
|
+
position: absolute;
|
5170
|
+
top: 48px;
|
5171
|
+
left: 2px;
|
5172
|
+
}
|
5173
|
+
|
5174
|
+
#datasetgroup-default {
|
5175
|
+
position: absolute;
|
5176
|
+
top: 47px;
|
5177
|
+
left: 79px;
|
5178
|
+
width: 80px;
|
5179
|
+
font-size: 12px;
|
5180
|
+
}
|
5181
|
+
|
5182
|
+
#datasetgroup-unit-lbl {
|
5183
|
+
position: absolute;
|
5184
|
+
top: 71px;
|
5185
|
+
left: 2px;
|
5186
|
+
}
|
5187
|
+
|
5188
|
+
#datasetgroup-unit {
|
5189
|
+
position: absolute;
|
5190
|
+
top: 70px;
|
5191
|
+
left: 32px;
|
5192
|
+
width: 70px;
|
5193
|
+
font-size: 12px;
|
5194
|
+
}
|
5195
|
+
|
5196
|
+
#datasetgroup-periodic {
|
5197
|
+
position: absolute;
|
5198
|
+
top: 90px;
|
5199
|
+
left: 0px;
|
5200
|
+
}
|
5201
|
+
|
5202
|
+
#datasetgroup-periodic-lbl {
|
5203
|
+
position: absolute;
|
5204
|
+
top: 92px;
|
5205
|
+
left: 22px;
|
5206
|
+
}
|
5207
|
+
|
5208
|
+
#datasetgroup-array {
|
5209
|
+
position: absolute;
|
5210
|
+
top: 90px;
|
5211
|
+
left: 77px;
|
5212
|
+
}
|
5213
|
+
|
5214
|
+
#datasetgroup-array-lbl {
|
5215
|
+
position: absolute;
|
5216
|
+
top: 92px;
|
5217
|
+
left: 99px;
|
5218
|
+
}
|
5219
|
+
|
5220
|
+
#datasetgroup-no-time-msg {
|
5221
|
+
position: absolute;
|
5222
|
+
top: 111px;
|
5223
|
+
left: 1px;
|
5224
|
+
width: 164px;
|
5225
|
+
height: 31px;
|
5226
|
+
z-index: 1;
|
5227
|
+
background-color: inherit;
|
5228
|
+
font-style: italic;
|
5229
|
+
padding-top: 15px;
|
5230
|
+
text-align: center;
|
5231
|
+
display: none;
|
5232
|
+
}
|
5233
|
+
|
5234
|
+
#datasetgroup-time-step-lbl {
|
5235
|
+
position: absolute;
|
5236
|
+
top: 113px;
|
5237
|
+
left: 2px;
|
5238
|
+
}
|
5239
|
+
|
5240
|
+
#datasetgroup-time-scale {
|
5241
|
+
position: absolute;
|
5242
|
+
top: 112px;
|
5243
|
+
left: 60px;
|
5244
|
+
width: 50px;
|
5245
|
+
font-size: 12px;
|
5246
|
+
}
|
5247
|
+
|
5248
|
+
#datasetgroup-time-unit {
|
5249
|
+
position: absolute;
|
5250
|
+
top: 113px;
|
5251
|
+
left: 116px;
|
5252
|
+
height: 19px;
|
5253
|
+
width: 45px;
|
5254
|
+
font-size: 12px;
|
5255
|
+
}
|
5256
|
+
|
5257
|
+
#datasetgroup-method-lbl {
|
5258
|
+
position: absolute;
|
5259
|
+
top: 137px;
|
5260
|
+
left: 2px;
|
5261
|
+
}
|
5262
|
+
|
5263
|
+
#datasetgroup-method {
|
5264
|
+
position: absolute;
|
5265
|
+
top: 135px;
|
5266
|
+
left: 50px;
|
5267
|
+
height: 21px;
|
5268
|
+
width: 111px;
|
5269
|
+
font-size: 12px;
|
5270
|
+
}
|
5271
|
+
|
5272
|
+
#datasetgroup-blackbox {
|
5273
|
+
position: absolute;
|
5274
|
+
bottom: 7px;
|
5275
|
+
left: 124px;
|
5276
|
+
width: 16px;
|
5277
|
+
height: 16px;
|
5278
|
+
font-size: 19px;
|
5279
|
+
cursor: pointer;
|
5280
|
+
color: #e0e0e0;
|
5281
|
+
}
|
5282
|
+
|
5283
|
+
#datasetgroup-outcome {
|
5284
|
+
position: absolute;
|
5285
|
+
bottom: 1px;
|
5286
|
+
left: 144px;
|
5287
|
+
width: 16px;
|
5288
|
+
height: 16px;
|
5289
|
+
cursor: pointer;
|
5290
|
+
}
|
5291
|
+
|
5292
|
+
#datasetgroup-io {
|
5293
|
+
position: absolute;
|
5294
|
+
bottom: -2px;
|
5295
|
+
left: 144px;
|
5296
|
+
font-size: 18px;
|
5297
|
+
color: Silver;
|
5298
|
+
cursor: pointer;
|
5299
|
+
}
|
5300
|
+
|
5301
|
+
#datasetgroup-separator {
|
5302
|
+
position: absolute;
|
5303
|
+
top: 23px;
|
5304
|
+
left: 165px;
|
5305
|
+
height: 164px;
|
5306
|
+
width: 3px;
|
5307
|
+
border-left: 1.5px Silver ridge;
|
5308
|
+
}
|
5309
|
+
|
5310
|
+
#datasetgroup-modif-header {
|
5311
|
+
position: absolute;
|
5312
|
+
top: 22px;
|
5313
|
+
left: 170px;
|
5314
|
+
font-style: italic;
|
5315
|
+
}
|
5316
|
+
|
5317
|
+
#datasetgroup-modif-titles {
|
5318
|
+
position: absolute;
|
5319
|
+
top: 38px;
|
5320
|
+
left: 170px;
|
5321
|
+
font-weight: 600;
|
5322
|
+
}
|
5323
|
+
|
5324
|
+
#datasetgroup-modif-scroll-area {
|
5325
|
+
position: absolute;
|
5326
|
+
top: 54px;
|
5327
|
+
left: 170px;
|
5328
|
+
width: 267px;
|
5329
|
+
height: 110px;
|
5330
|
+
overflow-y: auto;
|
5331
|
+
border-top: 1px solid Silver;
|
5332
|
+
}
|
5333
|
+
|
5334
|
+
#datasetgroup-modif-buttons {
|
5335
|
+
position: absolute;
|
5336
|
+
bottom: 1px;
|
5337
|
+
left: 170px;
|
5338
|
+
}
|
5339
|
+
|
5107
5340
|
/* the MONITOR DIALOG displays solver progress and messages */
|
5108
5341
|
#monitor-dlg {
|
5109
5342
|
display: none;
|
@@ -279,19 +279,19 @@ class Controller {
|
|
279
279
|
// Methods to ensure proper naming of entities.
|
280
280
|
|
281
281
|
cleanName(name) {
|
282
|
-
//
|
282
|
+
// Return `name` without the object-attribute separator |, backslashes,
|
283
283
|
// and leading and trailing whitespace, and with all internal whitespace
|
284
284
|
// reduced to a single space.
|
285
285
|
name = name.replace(this.OA_SEPARATOR, ' ')
|
286
286
|
.replace(/\||\\/g, ' ').trim()
|
287
287
|
.replace(/\s\s+/g, ' ');
|
288
|
-
// NOTE:
|
288
|
+
// NOTE: This may still result in a single space, which is not a name.
|
289
289
|
if(name === ' ') return '';
|
290
290
|
return name;
|
291
291
|
}
|
292
292
|
|
293
293
|
validName(name) {
|
294
|
-
//
|
294
|
+
// Return TRUE if `name` is a valid Linny-R entity name. These names
|
295
295
|
// must not be empty strings, may not contain brackets, backslashes or
|
296
296
|
// vertical bars, may not end with a colon, and must start with an
|
297
297
|
// underscore, a letter or a digit.
|
@@ -361,20 +361,84 @@ class Controller {
|
|
361
361
|
// Replace a leading colon in `name` by `prefix`.
|
362
362
|
// If `name` identifies a link or a constraint, this is applied to
|
363
363
|
// both node names.
|
364
|
+
// NOTE: To give the modeler more control over what to use as prefix,
|
365
|
+
// successive colons indicate that a shorter prefix should be used.
|
366
|
+
// For example, when the prefix is XXX: YYY: ZZZ, two colons mean
|
367
|
+
// "use only XXX: YYY:", three colons "use only XXX:", etc.
|
364
368
|
const
|
365
369
|
arrow = (name.indexOf(this.LINK_ARROW) >= 0 ?
|
366
370
|
this.LINK_ARROW : this.CONSTRAINT_ARROW),
|
367
371
|
nodes = name.split(arrow);
|
368
372
|
for(let i = 0; i < nodes.length; i++) {
|
369
|
-
|
373
|
+
// First check for the special case of just a leading colon plus
|
374
|
+
// possibly an entity attribute.
|
375
|
+
// NOTE:
|
376
|
+
const m = nodes[i].match(/^(:+)\s*(\|[^\|]*)/);
|
377
|
+
if(m) {
|
378
|
+
// Split prefix in parts.
|
379
|
+
const p = prefix.split(UI.PREFIXER);
|
380
|
+
// Remove last (empty!) substring.
|
381
|
+
p.pop();
|
382
|
+
// Shorten prefix by the number of successive colons minus 1.
|
383
|
+
for(let i = 1; i < m[1].length; i++) p.pop();
|
384
|
+
p.push('');
|
385
|
+
// New name is just the (shortened) prefix without its last ": ".
|
386
|
+
nodes[i] = p.join(UI.PREFIXER).replace(/:\s*$/, '') + m[2];
|
387
|
+
} else {
|
388
|
+
// Prefix is typically leading, so try to replace this first.
|
389
|
+
const m = nodes[i].match(/^(:+)/);
|
390
|
+
if(m) {
|
391
|
+
// Shorten prefix by the number of successive colons minus 1.
|
392
|
+
let p = prefix.split(UI.PREFIXER);
|
393
|
+
p.pop();
|
394
|
+
for(let i = 1; i < m[1].length; i++) p.pop();
|
395
|
+
p.push('');
|
396
|
+
nodes[i] = nodes[i].replace(/^:+\s*/, p.join(UI.PREFIXER));
|
397
|
+
} else {
|
398
|
+
// If no change, try to replace an embedded double prefix.
|
370
399
|
// NOTE: An embedded double prefix, e.g., "xxx: : yyy" indicates
|
371
400
|
// that the second colon+space should be replaced by the prefix.
|
372
|
-
|
373
|
-
|
374
|
-
|
401
|
+
const m = nodes[i].match(/(\w+):\s+(:+)\s+(\w+)/);
|
402
|
+
if(m) {
|
403
|
+
// Shorten prefix by the number of successive colons minus 1.
|
404
|
+
let p = prefix.split(UI.PREFIXER);
|
405
|
+
p.pop();
|
406
|
+
for(let i = 1; i < m[2].length; i++) p.pop();
|
407
|
+
p.push('');
|
408
|
+
prefix = p.join(UI.PREFIXER);
|
409
|
+
nodes[i] = `${m[1]}: ${prefix}${m[3]}`;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
}
|
375
413
|
}
|
376
414
|
return nodes.join(arrow);
|
377
415
|
}
|
416
|
+
|
417
|
+
entityPrefix(name) {
|
418
|
+
// Return the prefix of `name` with its trailing colon+space.
|
419
|
+
const
|
420
|
+
arrow = (name.indexOf(this.LINK_ARROW) >= 0 ?
|
421
|
+
this.LINK_ARROW : this.CONSTRAINT_ARROW),
|
422
|
+
nodes = name.split(arrow);
|
423
|
+
if(nodes.length === 1) return this.completePrefix(name);
|
424
|
+
// For names of links and constraints, it depends:
|
425
|
+
const
|
426
|
+
fn = nodes[0],
|
427
|
+
tn = nodes[1];
|
428
|
+
if(fn.indexOf(UI.PREFIXER) >= 0) {
|
429
|
+
if(tn.indexOf(UI.PREFIXER) >= 0) {
|
430
|
+
// If BOTH nodes are prefixed, use the longest prefix that these
|
431
|
+
// nodes have in common...
|
432
|
+
return UI.sharedPrefix(fn, tn) + UI.PREFIXER;
|
433
|
+
}
|
434
|
+
// .. otherwise, return the FROM node prefix.
|
435
|
+
return UI.completePrefix(fn);
|
436
|
+
}
|
437
|
+
// No FROM node prefix => return the TO node prefix (if any)
|
438
|
+
if(tn.indexOf(UI.PREFIXER) >= 0) return UI.completePrefix(tn);
|
439
|
+
// No prefixers => empty prefix.
|
440
|
+
return '';
|
441
|
+
}
|
378
442
|
|
379
443
|
tailNumber(name) {
|
380
444
|
// Return the string of digits at the end of `name`. If not there,
|
@@ -429,7 +493,6 @@ class Controller {
|
|
429
493
|
return pan1.length - pan2.length;
|
430
494
|
}
|
431
495
|
|
432
|
-
|
433
496
|
nameToID(name) {
|
434
497
|
// Return a name in lower case with link arrow replaced by three
|
435
498
|
// underscores, constraint link arrow by four underscores, and spaces
|
@@ -1272,7 +1335,7 @@ class ExperimentManager {
|
|
1272
1335
|
MODEL.round_sequence = asel.round_sequence;
|
1273
1336
|
}
|
1274
1337
|
}
|
1275
|
-
// Only now compute the simulation run time (number of time steps)
|
1338
|
+
// Only now compute the simulation run time (number of time steps).
|
1276
1339
|
xr.time_steps = MODEL.end_period - MODEL.start_period + 1;
|
1277
1340
|
VM.callback = this.callback;
|
1278
1341
|
// NOTE: Asynchronous call. All follow-up actions must be performed
|
@@ -1282,18 +1345,18 @@ class ExperimentManager {
|
|
1282
1345
|
}
|
1283
1346
|
|
1284
1347
|
processRun() {
|
1285
|
-
// This method is called by the solveBlocks method of the Virtual Machine
|
1348
|
+
// This method is called by the solveBlocks method of the Virtual Machine.
|
1286
1349
|
const x = MODEL.running_experiment;
|
1287
1350
|
if(!x) return;
|
1288
1351
|
const aci = x.active_combination_index;
|
1289
1352
|
if(MODEL.solved) {
|
1290
|
-
// NOTE: addresults will call processRestOfRun when completed
|
1353
|
+
// NOTE: addresults will call processRestOfRun when completed.
|
1291
1354
|
x.runs[aci].addResults();
|
1292
1355
|
} else {
|
1293
1356
|
// Do not add results...
|
1294
1357
|
UI.warn(`Model run #${aci} incomplete -- results will be invalid`);
|
1295
|
-
// ... but do perform the usual post-processing
|
1296
|
-
// NOTE:
|
1358
|
+
// ... but do perform the usual post-processing.
|
1359
|
+
// NOTE: When sensitivity analysis is being performed, switch back to SA.
|
1297
1360
|
if(SENSITIVITY_ANALYSIS.experiment) {
|
1298
1361
|
SENSITIVITY_ANALYSIS.processRestOfRun();
|
1299
1362
|
} else {
|
@@ -331,7 +331,7 @@ class GUIChartManager extends ChartManager {
|
|
331
331
|
}
|
332
332
|
|
333
333
|
updateSelector() {
|
334
|
-
//
|
334
|
+
// Add one option to the selector for each chart defined for the model.
|
335
335
|
// NOTE: Add the "new chart" option if it is not in the list.
|
336
336
|
MODEL.addChart(this.new_chart_title);
|
337
337
|
if(this.chart_index < 0) this.chart_index = 0;
|
@@ -545,16 +545,16 @@ class GUIChartManager extends ChartManager {
|
|
545
545
|
}
|
546
546
|
|
547
547
|
selectChart() {
|
548
|
-
//
|
548
|
+
// Set the selected chart to be the "active" chart.
|
549
549
|
const ci = parseInt(this.chart_selector.value);
|
550
|
-
// Deselect variable only if different chart is selected
|
550
|
+
// Deselect variable only if different chart is selected.
|
551
551
|
if(ci !== this.chart_index) this.variable_index = -1;
|
552
552
|
this.chart_index = ci;
|
553
553
|
this.updateDialog();
|
554
554
|
}
|
555
555
|
|
556
556
|
promptForTitle() {
|
557
|
-
//
|
557
|
+
// Prompt modeler for a new title for the current chart.
|
558
558
|
if(this.chart_index >= 0) {
|
559
559
|
this.rename_chart_modal.show();
|
560
560
|
const nct = document.getElementById('new-chart-title');
|
@@ -564,29 +564,29 @@ class GUIChartManager extends ChartManager {
|
|
564
564
|
}
|
565
565
|
|
566
566
|
renameChart() {
|
567
|
-
//
|
567
|
+
// Rename the current chart.
|
568
568
|
if(this.chart_index >= 0) {
|
569
|
-
const t = document.getElementById('new-chart-title').value
|
570
|
-
// Check if a chart with this title already exists
|
569
|
+
const t = UI.cleanName(document.getElementById('new-chart-title').value);
|
570
|
+
// Check if a chart with this title already exists.
|
571
571
|
const ci = MODEL.indexOfChart(t);
|
572
572
|
if(ci >= 0 && ci != this.chart_index) {
|
573
573
|
UI.warn(`A chart with title "${t}" already exists`);
|
574
574
|
} else {
|
575
575
|
const c = MODEL.charts[this.chart_index];
|
576
|
-
// Remember the old title of the chart-to-be-renamed
|
576
|
+
// Remember the old title of the chart-to-be-renamed.
|
577
577
|
const ot = c.title;
|
578
578
|
c.title = t;
|
579
|
-
// If the default '(new chart)' has been renamed, create a new one
|
579
|
+
// If the default '(new chart)' has been renamed, create a new one.
|
580
580
|
if(ot === this.new_chart_title) {
|
581
581
|
MODEL.addChart(ot);
|
582
582
|
}
|
583
|
-
// Update the chart index so that it points to the renamed chart
|
583
|
+
// Update the chart index so that it points to the renamed chart.
|
584
584
|
this.chart_index = MODEL.indexOfChart(t);
|
585
585
|
this.updateSelector();
|
586
|
-
// Redraw the chart if title is shown
|
586
|
+
// Redraw the chart if title is shown.
|
587
587
|
if(c.show_title) this.drawChart();
|
588
588
|
}
|
589
|
-
// Update
|
589
|
+
// Update dialogs that may refer to this chart.
|
590
590
|
UI.updateControllerDialogs('CFX');
|
591
591
|
}
|
592
592
|
this.rename_chart_modal.hide();
|
@@ -744,6 +744,7 @@ class GUIChartManager extends ChartManager {
|
|
744
744
|
chart.addWildcardVariables(dsm, indices);
|
745
745
|
} else if(dsm.selector.startsWith(':')) {
|
746
746
|
UI.notify('Plotting methods is work-in-progress!');
|
747
|
+
console.log('HERE dsm', dsm, 'expr', dsm.expression.text, 'indices', indices);
|
747
748
|
} else {
|
748
749
|
UI.notify(`Variable "${dsm.displayName}" cannot be plotted`);
|
749
750
|
}
|