linny-r 1.2.0 → 1.3.0
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 +6 -6
- package/console.js +2 -2
- package/package.json +2 -2
- package/static/images/paste.png +0 -0
- package/static/index.html +55 -6
- package/static/linny-r.css +100 -22
- package/static/scripts/linny-r-ctrl.js +26 -4
- package/static/scripts/linny-r-gui.js +940 -119
- package/static/scripts/linny-r-model.js +203 -37
- package/static/scripts/linny-r-utils.js +49 -11
- package/static/scripts/linny-r-vm.js +29 -18
package/README.md
CHANGED
@@ -25,7 +25,7 @@ Technical documentation will be developed on GitHub: https://github.com/pwgbots/
|
|
25
25
|
Linny-R is developed as a JavaScript package, and requires that **Node.js** is installed on your computer.
|
26
26
|
This software can be downloaded from <a href="https://nodejs.org" target="_blank">https://nodejs.org</a>.
|
27
27
|
Make sure that you choose the correct installer for your computer.
|
28
|
-
Linny-R is developed using the _current_ release. Presently (
|
28
|
+
Linny-R is developed using the _current_ release. Presently (June 2023) this is 20.3.0.
|
29
29
|
|
30
30
|
Run the installer and accept the default settings.
|
31
31
|
There is **no** need to install the optional _Tools for Native Modules_.
|
@@ -36,7 +36,7 @@ Verify the installation by typing:
|
|
36
36
|
|
37
37
|
``node --version``
|
38
38
|
|
39
|
-
The response should be the version number of Node.js, for example: v20.
|
39
|
+
The response should be the version number of Node.js, for example: v20.3.0.
|
40
40
|
|
41
41
|
## Installing Linny-R
|
42
42
|
It is advisable to install Linny-R in a directory on your computer, not in a cloud.
|
@@ -170,8 +170,8 @@ Open the Command Line Interface (CLI) of your computer, change to your `WORKING_
|
|
170
170
|
This response should be something similar to:
|
171
171
|
|
172
172
|
<pre>
|
173
|
-
Node.js server for Linny-R version 1.1
|
174
|
-
Node.js version: v20.
|
173
|
+
Node.js server for Linny-R version 1.2.1
|
174
|
+
Node.js version: v20.3.0
|
175
175
|
... etc.
|
176
176
|
</pre>
|
177
177
|
|
@@ -286,8 +286,8 @@ To install Inkscape, please look here: https://inkscape.org/release
|
|
286
286
|
Linny-R will automatically detect whether Inkscape is installed by searching for it in the environment variable PATH on your computer.
|
287
287
|
On a macOS computer, Linny-R will look for Inkscape in /Applications/Inkscape.app/Contents/MacOS.
|
288
288
|
|
289
|
-
**NOTE:** The current installation wizard for Inkscape (version 1.2)
|
290
|
-
|
289
|
+
**NOTE:** The current installation wizard for Inkscape (version 1.2.2) may **not** add the application to the PATH variable.
|
290
|
+
Please check whether you need to do this yourself.
|
291
291
|
|
292
292
|
## Using Linny-R console
|
293
293
|
|
package/console.js
CHANGED
@@ -196,7 +196,7 @@ class ConsoleMonitor {
|
|
196
196
|
return true;
|
197
197
|
}
|
198
198
|
|
199
|
-
submitBlockToSolver(
|
199
|
+
submitBlockToSolver() {
|
200
200
|
let top = MODEL.timeout_period;
|
201
201
|
if(VM.max_solver_time && top > VM.max_solver_time) {
|
202
202
|
top = VM.max_solver_time;
|
@@ -211,7 +211,7 @@ class ConsoleMonitor {
|
|
211
211
|
token: VM.solver_token,
|
212
212
|
block: VM.block_count,
|
213
213
|
round: VM.round_sequence[VM.current_round],
|
214
|
-
data:
|
214
|
+
data: VM.lines,
|
215
215
|
timeout: top
|
216
216
|
}));
|
217
217
|
VM.processServerResponse(data);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "linny-r",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.3.0",
|
4
4
|
"description": "Executable graphical language with WYSIWYG editor for MILP models",
|
5
5
|
"main": "server.js",
|
6
6
|
"scripts": {
|
@@ -29,4 +29,4 @@
|
|
29
29
|
"url": "https://github.com/pwgbots/linny-r/issues"
|
30
30
|
},
|
31
31
|
"homepage": "https://github.com/pwgbots/linny-r#readme"
|
32
|
-
}
|
32
|
+
}
|
package/static/images/paste.png
CHANGED
Binary file
|
package/static/index.html
CHANGED
@@ -28,7 +28,7 @@ implementation is made available via the Linny-R web site.
|
|
28
28
|
-->
|
29
29
|
|
30
30
|
<!--
|
31
|
-
Copyright (c) 2017-
|
31
|
+
Copyright (c) 2017-2023 Delft University of Technology
|
32
32
|
|
33
33
|
Permission is hereby granted, free of charge, to any person obtaining
|
34
34
|
a copy of this software and associated documentation files (the
|
@@ -239,7 +239,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
239
239
|
<img id="load-btn" class="btn enab" src="images/open.png"
|
240
240
|
title="Load model (Ctrl-L)">
|
241
241
|
<img id="settings-btn" class="btn enab" src="images/settings.png"
|
242
|
-
title="Change settings (
|
242
|
+
title="Change model settings (Alt-M)">
|
243
243
|
<img id="save-btn" class="btn enab" src="images/save.png"
|
244
244
|
title="Save model (Ctrl-S)">
|
245
245
|
<img id="repository-btn" class="btn enab" src="images/repository.png"
|
@@ -321,6 +321,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
321
321
|
<td id="step-sep">
|
322
322
|
<img id="stepforward-btn" class="sbtn senab" src="images/forward.png">
|
323
323
|
</td>
|
324
|
+
<td id="issue-panel">
|
325
|
+
<span id="prev-issue">◁</span>
|
326
|
+
<span id="issue-nr"></span>
|
327
|
+
<span id="next-issue">▷</span>
|
328
|
+
</td>
|
324
329
|
<td id="info-line" title="Status bar"></td>
|
325
330
|
<td id="autosave-sep">
|
326
331
|
<img id="autosave-btn" class="btn enab" src="images/restore.png">
|
@@ -347,7 +352,9 @@ and move the cursor over the status bar">
|
|
347
352
|
<img id="note-btn" class="btn toggle enab sep" src="images/note.png"
|
348
353
|
title="Add note">
|
349
354
|
<img id="clone-btn" class="btn disab sep" src="images/clone.png"
|
350
|
-
title="
|
355
|
+
title="Copy selection (Ctrl-C) – Alt-click to clone (Alt-C)">
|
356
|
+
<img id="paste-btn" class="btn disab sep" src="images/paste.png"
|
357
|
+
title="Paste selection (Ctrl-V) -- WORK IN PROGESS!">
|
351
358
|
<img id="delete-btn" class="btn disab sep" src="images/delete.png"
|
352
359
|
title="Delete">
|
353
360
|
<img id="undo-btn" class="btn enab" src="images/undo.png"
|
@@ -851,6 +858,26 @@ NOTE: Unit symbols are case-sensitive, so BTU ≠ Btu">
|
|
851
858
|
</div>
|
852
859
|
</div>
|
853
860
|
|
861
|
+
<!-- the CONFIRM LOAD modal asks to confirm to load model from repository -->
|
862
|
+
<div id="confirm-load-from-repo-modal" class="modal">
|
863
|
+
<div id="confirm-load-from-repo-dlg" class="inp-dlg">
|
864
|
+
<div class="dlg-title" style="background-color: #cc88b0">
|
865
|
+
Confirm load model
|
866
|
+
</div>
|
867
|
+
<div id="confirm-load-from-repo-msg">
|
868
|
+
Loading model
|
869
|
+
<span id="confirm-load-from-repo-mod-name"></span>
|
870
|
+
will discard changes you made to the current model. Continue?
|
871
|
+
</div>
|
872
|
+
<div id="confirm-load-from-repo-buttons">
|
873
|
+
<img class="ok-btn big-btn" src="images/ok.png">
|
874
|
+
Yes
|
875
|
+
<img class="cancel-btn big-btn" src="images/cancel.png">
|
876
|
+
No
|
877
|
+
</div>
|
878
|
+
</div>
|
879
|
+
</div>
|
880
|
+
|
854
881
|
<!-- the CONFIRM DELETE modal asks to confirm to delete module from repository -->
|
855
882
|
<div id="confirm-delete-from-repo-modal" class="modal">
|
856
883
|
<div id="confirm-delete-from-repo-dlg" class="inp-dlg">
|
@@ -1510,7 +1537,8 @@ NOTE: Unit symbols are case-sensitive, so BTU ≠ Btu">
|
|
1510
1537
|
<div id="ds-filter-bar">
|
1511
1538
|
<input id="ds-filter-text" type="text"
|
1512
1539
|
placeholder="(name filtering pattern)"
|
1513
|
-
title="Pattern may contain logical & (AND), | (OR) and ^ (NOT)
|
1540
|
+
title="Pattern may contain logical & (AND), | (OR) and ^ (NOT)
|
1541
|
+
Start with = to find exact match, with ~ to match first characters">
|
1514
1542
|
</div>
|
1515
1543
|
<div id="dataset-scroll-area">
|
1516
1544
|
<table id="dataset-table">
|
@@ -1564,6 +1592,9 @@ NOTE: Unit symbols are case-sensitive, so BTU ≠ Btu">
|
|
1564
1592
|
<img id="ds-delete-modif-btn" class="btn disab"
|
1565
1593
|
src="images/delete.png" title="Delete selected modifier"
|
1566
1594
|
style="margin-left: 20px">
|
1595
|
+
<img id="ds-convert-modif-btn" class="btn enab blink"
|
1596
|
+
src="images/dataset.png" title="Convert modifiers to prefixed datasets"
|
1597
|
+
style="margin-left: 20px; display: none">
|
1567
1598
|
</div>
|
1568
1599
|
<div id="dataset-resize" class="resizer"></div>
|
1569
1600
|
</div>
|
@@ -1584,7 +1615,7 @@ NOTE: Unit symbols are case-sensitive, so BTU ≠ Btu">
|
|
1584
1615
|
<div id="rename-dataset-modal" class="modal">
|
1585
1616
|
<div id="rename-dataset-dlg" class="inp-dlg">
|
1586
1617
|
<div class="dlg-title">
|
1587
|
-
Rename dataset
|
1618
|
+
<span id="rename-dataset-title">Rename dataset</span>
|
1588
1619
|
<img class="cancel-btn" src="images/cancel.png">
|
1589
1620
|
<img class="ok-btn" src="images/ok.png">
|
1590
1621
|
</div>
|
@@ -1623,6 +1654,23 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
1623
1654
|
</div>
|
1624
1655
|
</div>
|
1625
1656
|
|
1657
|
+
<!-- the CONVERT MODIFIER prompts for the new name of a dataset -->
|
1658
|
+
<div id="convert-modifiers-modal" class="modal">
|
1659
|
+
<div id="convert-modifiers-dlg" class="inp-dlg">
|
1660
|
+
<div class="dlg-title">
|
1661
|
+
Convert modifiers to datasets
|
1662
|
+
<img class="cancel-btn" src="images/cancel.png">
|
1663
|
+
<img class="ok-btn" src="images/ok.png">
|
1664
|
+
</div>
|
1665
|
+
<div style="margin: 4px">
|
1666
|
+
Each modifier will become a dataset
|
1667
|
+
<tt><em>prefix</em>: <em>selector</em></tt>
|
1668
|
+
using this prefix:
|
1669
|
+
</div>
|
1670
|
+
<input id="convert-modifiers-prefix" type="text" autocomplete="off">
|
1671
|
+
</div>
|
1672
|
+
</div>
|
1673
|
+
|
1626
1674
|
<!-- the SERIES dialog presents the properties of the time series
|
1627
1675
|
data of the selected dataset, including a text area for copy/paste
|
1628
1676
|
of numbers while showing the line count and checking for correct
|
@@ -1839,7 +1887,8 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
1839
1887
|
<div style="padding: 4px; width: 100px">
|
1840
1888
|
<div id="variable-color-div">
|
1841
1889
|
<div style="display:inline-block; vertical-align:top">Color:</div>
|
1842
|
-
<div id="variable-color"></div>
|
1890
|
+
<div id="variable-color" title="Click to copy, Shift-click to paste"></div>
|
1891
|
+
<div id="variable-paste-color"></div>
|
1843
1892
|
</div>
|
1844
1893
|
<div id="variable-scale-div" style="margin-top: 3px">
|
1845
1894
|
<div style="display:inline-block; vertical-align:top; margin-top: 2px">
|
package/static/linny-r.css
CHANGED
@@ -10,7 +10,7 @@ file that implements the graphical user interface for Linny-R.
|
|
10
10
|
*/
|
11
11
|
|
12
12
|
/*
|
13
|
-
Copyright (c) 2017-
|
13
|
+
Copyright (c) 2017-2023 Delft University of Technology
|
14
14
|
|
15
15
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
16
16
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -413,6 +413,7 @@ textarea {
|
|
413
413
|
#zoom-sep,
|
414
414
|
#step-sep,
|
415
415
|
#info-line,
|
416
|
+
#issue-panel,
|
416
417
|
#autosave-sep {
|
417
418
|
border-right: 1px solid #e2d8e8;
|
418
419
|
}
|
@@ -507,6 +508,36 @@ div.notification-msg.first-msg {
|
|
507
508
|
color: black;
|
508
509
|
}
|
509
510
|
|
511
|
+
#issue-panel {
|
512
|
+
display: none;
|
513
|
+
background-color: Yellow;
|
514
|
+
white-space: nowrap;
|
515
|
+
padding: 0 3px;
|
516
|
+
}
|
517
|
+
|
518
|
+
#issue-nr {
|
519
|
+
padding: 0 4px;
|
520
|
+
cursor: pointer;
|
521
|
+
}
|
522
|
+
|
523
|
+
#prev-issue,
|
524
|
+
#next-issue {
|
525
|
+
cursor: pointer;
|
526
|
+
}
|
527
|
+
|
528
|
+
#prev-issue:hover,
|
529
|
+
#issue-nr:hover,
|
530
|
+
#next-issue:hover {
|
531
|
+
color: Orange;
|
532
|
+
}
|
533
|
+
|
534
|
+
#prev-issue.disab,
|
535
|
+
#next-issue.disab {
|
536
|
+
cursor: default;
|
537
|
+
pointer-events: none;
|
538
|
+
color: #e8d898;
|
539
|
+
}
|
540
|
+
|
510
541
|
/* Modal dialogs cover the entire browser window with a dark,
|
511
542
|
semi-transparent DIV that ignores mouse events. Their z-index
|
512
543
|
is 100+ so that they cover "stay-on-top" dialogs. */
|
@@ -1924,10 +1955,6 @@ td.it {
|
|
1924
1955
|
font-style: italic;
|
1925
1956
|
}
|
1926
1957
|
|
1927
|
-
td.series {
|
1928
|
-
|
1929
|
-
}
|
1930
|
-
|
1931
1958
|
td.io {
|
1932
1959
|
width: 12px;
|
1933
1960
|
}
|
@@ -2095,84 +2122,103 @@ tr.def-sel {
|
|
2095
2122
|
font-weight: bold;
|
2096
2123
|
}
|
2097
2124
|
|
2098
|
-
|
2125
|
+
tr.dataset > td > div {
|
2126
|
+
display: inline-block;
|
2127
|
+
}
|
2128
|
+
|
2129
|
+
div.ds-indent {
|
2130
|
+
color: #909090;
|
2131
|
+
text-align: right;
|
2132
|
+
font-weight: normal !important;
|
2133
|
+
margin-right: 2px;
|
2134
|
+
margin-left: 3px;
|
2135
|
+
}
|
2136
|
+
|
2137
|
+
div.tree-btn {
|
2138
|
+
color: #909090;
|
2139
|
+
margin-right: 3px;
|
2140
|
+
cursor: pointer;
|
2141
|
+
margin-left: -13px;
|
2142
|
+
}
|
2143
|
+
|
2144
|
+
div.modif::before {
|
2099
2145
|
content: ' \2045';
|
2100
2146
|
color: #b00080;
|
2101
2147
|
margin-right: 2px;
|
2102
2148
|
}
|
2103
2149
|
|
2104
|
-
|
2150
|
+
div.outcome::before {
|
2105
2151
|
content: ' \25C8';
|
2106
2152
|
color: #b00080;
|
2107
2153
|
margin-right: 1px;
|
2108
2154
|
}
|
2109
2155
|
|
2110
|
-
|
2156
|
+
div.array::before {
|
2111
2157
|
content: ' \2263';
|
2112
2158
|
color: #b00080;
|
2113
2159
|
margin-right: 1px;
|
2114
2160
|
}
|
2115
2161
|
|
2116
|
-
|
2162
|
+
div.series::before {
|
2117
2163
|
content: ' \28B8';
|
2118
2164
|
color: #b00080;
|
2119
|
-
margin-left: -
|
2165
|
+
margin-left: -4px;
|
2120
2166
|
}
|
2121
2167
|
|
2122
|
-
|
2168
|
+
div.outcome.modif::before {
|
2123
2169
|
content: ' \25C8\2045';
|
2124
2170
|
color: #b00080;
|
2125
2171
|
margin-right: 2px;
|
2126
2172
|
}
|
2127
2173
|
|
2128
|
-
|
2174
|
+
div.array.modif::before {
|
2129
2175
|
content: ' \2263\2045';
|
2130
2176
|
color: #b00080;
|
2131
2177
|
margin-right: 1px;
|
2132
2178
|
}
|
2133
2179
|
|
2134
|
-
|
2180
|
+
div.series.modif::before {
|
2135
2181
|
content: ' \28B8\2045';
|
2136
2182
|
color: #b00080;
|
2137
|
-
margin-left: -
|
2183
|
+
margin-left: -4px;
|
2138
2184
|
}
|
2139
2185
|
|
2140
|
-
|
2186
|
+
div.blackbox::before {
|
2141
2187
|
content: ' \25FC';
|
2142
2188
|
color: #b00080;
|
2143
2189
|
}
|
2144
2190
|
|
2145
|
-
|
2191
|
+
div.blackbox.series::before {
|
2146
2192
|
content: ' \25FC\28B8';
|
2147
2193
|
color: #b00080;
|
2148
2194
|
}
|
2149
2195
|
|
2150
|
-
|
2196
|
+
div.blackbox.array::before {
|
2151
2197
|
content: ' \25FC\2263';
|
2152
2198
|
color: #b00080;
|
2153
2199
|
}
|
2154
2200
|
|
2155
|
-
|
2201
|
+
div.blackbox.outcome::before {
|
2156
2202
|
content: ' \25FC\25C8';
|
2157
2203
|
color: #b00080;
|
2158
2204
|
}
|
2159
2205
|
|
2160
|
-
|
2206
|
+
div.blackbox.modif::before {
|
2161
2207
|
content: ' \25FC\2045';
|
2162
2208
|
color: #b00080;
|
2163
2209
|
}
|
2164
2210
|
|
2165
|
-
|
2211
|
+
div.blackbox.series.modif::before {
|
2166
2212
|
content: ' \25FC\28B8\2045';
|
2167
2213
|
color: #b00080;
|
2168
2214
|
}
|
2169
2215
|
|
2170
|
-
|
2216
|
+
div.blackbox.array.modif::before {
|
2171
2217
|
content: ' \25FC\2263\2045';
|
2172
2218
|
color: #b00080;
|
2173
2219
|
}
|
2174
2220
|
|
2175
|
-
|
2221
|
+
div.blackbox.outcome.modif::before {
|
2176
2222
|
content: ' \25FC\25C8\2045';
|
2177
2223
|
color: #b00080;
|
2178
2224
|
}
|
@@ -2298,6 +2344,17 @@ td.equation-expression {
|
|
2298
2344
|
bottom: 5px;
|
2299
2345
|
}
|
2300
2346
|
|
2347
|
+
/* CONVERT MODIFIERS modal dialog */
|
2348
|
+
#convert-modifiers-dlg {
|
2349
|
+
width: 220px;
|
2350
|
+
height: 84px;
|
2351
|
+
}
|
2352
|
+
|
2353
|
+
#convert-modifiers-prefix {
|
2354
|
+
margin: 3px;
|
2355
|
+
width: calc(100% - 8px);
|
2356
|
+
}
|
2357
|
+
|
2301
2358
|
/* SERIES modal dialog */
|
2302
2359
|
#series-dlg {
|
2303
2360
|
width: 165px;
|
@@ -2742,6 +2799,17 @@ img.v-disab {
|
|
2742
2799
|
height: 15px;
|
2743
2800
|
border: 1px solid Black;
|
2744
2801
|
background-color: #c00000;
|
2802
|
+
cursor: pointer;
|
2803
|
+
}
|
2804
|
+
|
2805
|
+
#variable-paste-color {
|
2806
|
+
display: none;
|
2807
|
+
vertical-align: top;
|
2808
|
+
margin-left: 3px;
|
2809
|
+
width: 13px;
|
2810
|
+
height: 13px;
|
2811
|
+
border: 1px solid Silver;
|
2812
|
+
background-color: #c00000;
|
2745
2813
|
}
|
2746
2814
|
|
2747
2815
|
#variable-scale {
|
@@ -4036,6 +4104,11 @@ select.i-param {
|
|
4036
4104
|
max-width: calc(100% - 15px);
|
4037
4105
|
}
|
4038
4106
|
|
4107
|
+
#confirm-load-from-repo-dlg {
|
4108
|
+
width: 400px;
|
4109
|
+
height: 85px;
|
4110
|
+
}
|
4111
|
+
|
4039
4112
|
#confirm-delete-from-repo-dlg {
|
4040
4113
|
width: 270px;
|
4041
4114
|
height: 120px;
|
@@ -4047,12 +4120,14 @@ select.i-param {
|
|
4047
4120
|
font-weight: bold;
|
4048
4121
|
}
|
4049
4122
|
|
4123
|
+
#confirm-load-from-repo-mod-name,
|
4050
4124
|
#confirm-delete-from-repo-mod-name {
|
4051
4125
|
word-break: keep-all;
|
4052
4126
|
white-space: nowrap;
|
4053
4127
|
font-family: monospace;
|
4054
4128
|
}
|
4055
4129
|
|
4130
|
+
#confirm-load-from-repo-msg,
|
4056
4131
|
#confirm-delete-from-repo-msg {
|
4057
4132
|
height: calc(100% - 55px);
|
4058
4133
|
}
|
@@ -4577,6 +4652,7 @@ div.call-stack-expr {
|
|
4577
4652
|
height: min-content;
|
4578
4653
|
}
|
4579
4654
|
|
4655
|
+
#confirm-load-from-repo-msg,
|
4580
4656
|
#confirm-delete-from-repo-msg,
|
4581
4657
|
#check-update-msg {
|
4582
4658
|
width: calc(100% - 8px);
|
@@ -4585,6 +4661,7 @@ div.call-stack-expr {
|
|
4585
4661
|
}
|
4586
4662
|
|
4587
4663
|
#confirm-move-buttons,
|
4664
|
+
#confirm-load-from-repo-buttons,
|
4588
4665
|
#confirm-delete-from-repo-buttons,
|
4589
4666
|
#check-update-buttons {
|
4590
4667
|
width: 100%;
|
@@ -4595,6 +4672,7 @@ div.call-stack-expr {
|
|
4595
4672
|
}
|
4596
4673
|
|
4597
4674
|
#confirm-move-buttons > img,
|
4675
|
+
#confirm-load-from-repo-buttons > img,
|
4598
4676
|
#confirm-delete-from-repo-buttons > img,
|
4599
4677
|
#check-update-buttons > img {
|
4600
4678
|
float: none;
|
@@ -12,7 +12,7 @@ file all have their graphical extensions in file linny-r-gui.js.
|
|
12
12
|
*/
|
13
13
|
|
14
14
|
/*
|
15
|
-
Copyright (c) 2017-
|
15
|
+
Copyright (c) 2017-2023 Delft University of Technology
|
16
16
|
|
17
17
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
18
18
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -290,15 +290,32 @@ class Controller {
|
|
290
290
|
validName(name) {
|
291
291
|
// Returns TRUE if `name` is a valid Linny-R entity name. These names
|
292
292
|
// must not be empty strings, may not contain brackets, backslashes or
|
293
|
-
// vertical bars,
|
294
|
-
//
|
293
|
+
// vertical bars, may not end with a colon, and must start with an
|
294
|
+
// underscore, a letter or a digit. This is enforced mainly to
|
295
|
+
// preclude parsing issues with variable names
|
295
296
|
// NOTE: normalize to also accept letters with accents
|
296
297
|
if(name === this.TOP_CLUSTER_NAME) return true;
|
297
298
|
name = name.normalize('NFKD').trim();
|
298
|
-
return name && !name.match(/\[\\\|\]/) &&
|
299
|
+
return name && !name.match(/\[\\\|\]/) && !name.endsWith(':') &&
|
299
300
|
(name.startsWith(this.BLACK_BOX) || name[0].match(/[\w]/));
|
300
301
|
}
|
301
302
|
|
303
|
+
prefixesAndName(name) {
|
304
|
+
// Returns name split exclusively at '[non-space]: [non-space]'
|
305
|
+
const
|
306
|
+
s = name.split(this.PREFIXER),
|
307
|
+
pan = [s[0]];
|
308
|
+
for(let i = 1; i < s.length; i++) {
|
309
|
+
const j = pan.length - 1;
|
310
|
+
if(s[i].startsWith(' ') || (i > 0 && pan[j].endsWith(' '))) {
|
311
|
+
pan[j] += s[i];
|
312
|
+
} else {
|
313
|
+
pan.push(s[i]);
|
314
|
+
}
|
315
|
+
}
|
316
|
+
return pan;
|
317
|
+
}
|
318
|
+
|
302
319
|
nameToID(name) {
|
303
320
|
// Returns a name in lower case with link arrow replaced by three
|
304
321
|
// underscores, constraint link arrow by four underscores, and spaces
|
@@ -466,6 +483,7 @@ class Controller {
|
|
466
483
|
rotatingIcon() {}
|
467
484
|
setProgressNeedle() {}
|
468
485
|
updateTimeStep() {}
|
486
|
+
updateIssuePanel() {}
|
469
487
|
updateDraggableDialogs() {}
|
470
488
|
logHeapSize() {}
|
471
489
|
|
@@ -974,6 +992,9 @@ class SensitivityAnalysis {
|
|
974
992
|
// Class ExperimentManager controls the collection of experiments of the model
|
975
993
|
class ExperimentManager {
|
976
994
|
constructor() {
|
995
|
+
// NOTE: the properties below are relevant only for the GUI
|
996
|
+
this.experiment_table = null;
|
997
|
+
this.focal_table = null;
|
977
998
|
}
|
978
999
|
|
979
1000
|
reset() {
|
@@ -1005,6 +1026,7 @@ class ExperimentManager {
|
|
1005
1026
|
selectExperiment(title) {
|
1006
1027
|
const xi = MODEL.indexOfExperiment(title);
|
1007
1028
|
this.selected_experiment = (xi < 0 ? null : MODEL.experiments[xi]);
|
1029
|
+
this.focal_table = this.experiment_table;
|
1008
1030
|
this.updateDialog();
|
1009
1031
|
}
|
1010
1032
|
|