linny-r 2.0.7 → 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 +74 -21
- package/static/linny-r.css +22 -16
- package/static/scripts/iro.min.js +7 -7
- package/static/scripts/linny-r-ctrl.js +51 -72
- package/static/scripts/linny-r-gui-actor-manager.js +23 -33
- package/static/scripts/linny-r-gui-chart-manager.js +50 -45
- 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 +143 -32
- 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 +53 -46
- 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 +35 -27
- package/static/scripts/linny-r-vm.js +807 -905
- package/static/show-png.html +0 -113
package/README.md
CHANGED
@@ -36,8 +36,8 @@ Linny-R is developed as a JavaScript package, and requires that **Node.js**
|
|
36
36
|
is installed on your computer. This software can be downloaded from
|
37
37
|
<a href="https://nodejs.org" target="_blank">https://nodejs.org</a>.
|
38
38
|
Make sure that you choose the correct installer for your computer.
|
39
|
-
Linny-R is developed using the _current_ release. Presently (
|
40
|
-
this is
|
39
|
+
Linny-R is developed using the _current_ release. Presently (May 2025)
|
40
|
+
this is 24.1.0.
|
41
41
|
|
42
42
|
Run the installer and accept the default settings.
|
43
43
|
There is <u>**no**</u> need to install the optional _Tools for Native Modules_.
|
@@ -48,7 +48,7 @@ Verify the installation by typing:
|
|
48
48
|
|
49
49
|
``node --version``
|
50
50
|
|
51
|
-
The response should be the version number of Node.js, for example:
|
51
|
+
The response should be the version number of Node.js, for example: v24.1.0.
|
52
52
|
|
53
53
|
## Installing Linny-R
|
54
54
|
It is advisable to install Linny-R in a directory on your computer, **not**
|
@@ -116,7 +116,6 @@ The `linny-r` package directory should contain this file `README.md`, the files
|
|
116
116
|
`static`. This `static` directory should contain three HTML files:
|
117
117
|
|
118
118
|
* `index.html` (the browser-based GUI)
|
119
|
-
* `show-png.html` (to render SVG diagrams as PNG images)
|
120
119
|
* `show-diff.html` (to display differences between two Linny-R models)
|
121
120
|
|
122
121
|
It should also contain the style sheet `linny-r.css` required by the GUI.
|
@@ -379,7 +378,6 @@ You can customize Linny-R by adding more arguments to the `node` command
|
|
379
378
|
in the launch script:
|
380
379
|
|
381
380
|
<pre>
|
382
|
-
dpi=[number] to overrule the default resolution (300 dpi) for Inkscape
|
383
381
|
launch to automatically launch Linny-R in your default browser
|
384
382
|
port=[number] to overrule the default port number (5050)
|
385
383
|
solver=[name] to overrule the default sequence (Gurobi, MOSEK, CPLEX, SCIP, LP_solve)
|
@@ -402,8 +400,6 @@ The sub-directories of this directory `user` are used by Linny-R to store files.
|
|
402
400
|
* `channel` and `callback` will be used to interact with Linny-R via its _Receiver_
|
403
401
|
* `data` will be used by the _Dataset Manager_ to locate datasets for which
|
404
402
|
a path has been specified
|
405
|
-
* `diagrams` will be used to render Scalable Vector Graphics (SVG) files as
|
406
|
-
Portable Network Graphics (PNG) using Inkscape (if installed)
|
407
403
|
* `models` will contain models that you saved by Shift-clicking on the
|
408
404
|
_Save_ button, or using the keyboard shortcut Ctrl-Shift-S
|
409
405
|
* `modules` will contain models stored in the `local host` _repository_
|
@@ -419,39 +415,6 @@ The sub-directories of this directory `user` are used by Linny-R to store files.
|
|
419
415
|
> option. This will create a new, empty workspace in the specified path.
|
420
416
|
> It will **not** affect or duplicate information from existing workspaces.
|
421
417
|
|
422
|
-
## Installing Inkscape
|
423
|
-
|
424
|
-
Linny-R creates its diagrams and charts as SVG images.
|
425
|
-
When you download a diagram, it will be saved as a .svg file.
|
426
|
-
These files can be viewed and edited using Inkscape, an open source
|
427
|
-
vector graphics editor.
|
428
|
-
|
429
|
-
As it may be tedious to first save a diagram as SVG and then render it
|
430
|
-
manually as a bitmap image, Linny-R features a *Render diagram as bitmap*
|
431
|
-
button on the top toolbar, and on the bottom toolbar of the _Chart manager_.
|
432
|
-
When you click it, Linny-R will send the image as SVG to the server.
|
433
|
-
The server script will save the SVG in the `user/diagrams` sub-directory,
|
434
|
-
and then try to execute an Inkscape command that will convert this SVG to
|
435
|
-
a PNG image file in the same directory.
|
436
|
-
The file name will be `diagram-(date and time).png`.
|
437
|
-
Meanwhile, the browser will have opened a new tab that will be "waiting"
|
438
|
-
for this PNG image to become available.
|
439
|
-
If rendering was successful, the image will appear in this browser tab;
|
440
|
-
if rendering failed, the original SVG image will be shown.
|
441
|
-
|
442
|
-
To install Inkscape, please look here:
|
443
|
-
<a href="https://inkscape.org/release"
|
444
|
-
target="_blank">https://inkscape.org/release</a>
|
445
|
-
|
446
|
-
Linny-R will automatically detect whether Inkscape is installed by searching
|
447
|
-
for it in the environment variable PATH on your computer. On a macOS computer,
|
448
|
-
Linny-R will look for Inkscape in `/Applications/Inkscape.app/Contents/MacOS`.
|
449
|
-
|
450
|
-
> [!NOTE]
|
451
|
-
> The installation wizard for Inkscape (version 1.3) may **not**
|
452
|
-
> add the application to the PATH variable. Please check whether you need to
|
453
|
-
> do this yourself.
|
454
|
-
|
455
418
|
## Using Linny-R console
|
456
419
|
|
457
420
|
The console-only version of Linny-R allows you to run a Linny-R model without
|
package/package.json
CHANGED
package/server.js
CHANGED
@@ -1265,29 +1265,27 @@ function rcvrCallBack(res, rpath, rfile, script) {
|
|
1265
1265
|
const STATIC_FILES = {
|
1266
1266
|
// MIME types of files that can be served
|
1267
1267
|
extensions: {
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1268
|
+
js: 'application/javascript',
|
1269
|
+
xml: 'application/xml',
|
1270
|
+
wav: 'audio/x-wav',
|
1271
|
+
ttc: 'font/collection',
|
1272
|
+
otf: 'font/otf',
|
1273
|
+
ttf: 'font/ttf',
|
1274
|
+
icns: 'image/icns',
|
1275
|
+
png: 'image/png',
|
1276
|
+
svg: 'image/svg+xml',
|
1277
|
+
ico: 'image/x-icon',
|
1278
|
+
css: 'text/css',
|
1279
|
+
html: 'text/html',
|
1280
|
+
txt: 'text/plain'
|
1281
|
+
},
|
1282
1282
|
// Subdirectories of (main)/static/ directory from which files with
|
1283
1283
|
// accepted MIME types can be served
|
1284
1284
|
directories: {
|
1285
1285
|
'/scripts': ['js'],
|
1286
1286
|
'/images': ['icns', 'ico', 'png', 'svg'],
|
1287
1287
|
'/fonts': ['otf', 'ttc', 'ttf'],
|
1288
|
-
'/sounds': ['wav']
|
1289
|
-
// NOTE: diagrams will actually be served from (main)/user/diagrams/
|
1290
|
-
'/diagrams': ['png', 'svg']
|
1288
|
+
'/sounds': ['wav']
|
1291
1289
|
},
|
1292
1290
|
// Files that can be served from the (main)/static/ directory itself
|
1293
1291
|
files: [
|
@@ -1417,17 +1415,11 @@ function permittedFile(path) {
|
|
1417
1415
|
}
|
1418
1416
|
|
1419
1417
|
function serveStaticFile(res, path) {
|
1420
|
-
// Serve the specified path (if permitted: only
|
1418
|
+
// Serve the specified path (if permitted: only static files)
|
1421
1419
|
if(path === '/' || path === '') path = '/index.html';
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
path = WORKING_DIRECTORY + '/user' + path;
|
1426
|
-
} else {
|
1427
|
-
// Other files from the (main)/static/ subdirectory
|
1428
|
-
logAction('Static file: ' + path);
|
1429
|
-
path = MODULE_DIRECTORY + '/static' + path;
|
1430
|
-
}
|
1420
|
+
// Serve files from the (main)/static/ subdirectory
|
1421
|
+
logAction('Static file: ' + path);
|
1422
|
+
path = MODULE_DIRECTORY + '/static' + path;
|
1431
1423
|
fs.readFile(path, (err, data) => {
|
1432
1424
|
if(err) {
|
1433
1425
|
console.log(err);
|
@@ -1442,75 +1434,6 @@ function serveStaticFile(res, path) {
|
|
1442
1434
|
});
|
1443
1435
|
}
|
1444
1436
|
|
1445
|
-
function convertSVGtoPNG(req, res, sp) {
|
1446
|
-
// Convert SVG data from browser to PNG image using Inkscape
|
1447
|
-
// NOTE: images can be huge, so send only the file name as response;
|
1448
|
-
// Linny-R will open a new browser window, load the file, and display it
|
1449
|
-
const
|
1450
|
-
svg = decodeURI(atob(sp.get('data'))),
|
1451
|
-
// Use current time as file name
|
1452
|
-
fn = 'diagram-' +
|
1453
|
-
(new Date()).toISOString().slice(0, 19).replace(/[\-\:]/g, ''),
|
1454
|
-
fp = path.join(WORKSPACE.diagrams, fn);
|
1455
|
-
// NOTE: use binary encoding for SVG file
|
1456
|
-
logAction('Saving SVG file: ' + fp);
|
1457
|
-
try {
|
1458
|
-
fs.writeFileSync(fp + '.svg', svg);
|
1459
|
-
} catch(error) {
|
1460
|
-
console.log('WARNING: Failed to save SVG --', error);
|
1461
|
-
}
|
1462
|
-
// Use Inkscape to convert SVG to the requested format
|
1463
|
-
if(SETTINGS.inkscape) {
|
1464
|
-
logAction('Rendering image');
|
1465
|
-
let
|
1466
|
-
cmd = SETTINGS.inkscape,
|
1467
|
-
svg = fp + '.svg';
|
1468
|
-
// Enclose paths in double quotes if they contain spaces
|
1469
|
-
if(cmd.indexOf(' ') >= 0) cmd = `"${cmd}"`;
|
1470
|
-
if(svg.indexOf(' ') >= 0) svg = `"${svg}"`;
|
1471
|
-
cmd += ` --export-type=png --export-dpi=${SETTINGS.dpi} ${svg}`;
|
1472
|
-
console.log(cmd);
|
1473
|
-
child_process.exec(cmd,
|
1474
|
-
(error, stdout, stderr) => {
|
1475
|
-
let ext = '.svg';
|
1476
|
-
console.log(stdout);
|
1477
|
-
if(error) {
|
1478
|
-
console.log('WARNING: Failed to run Inkscape --', error);
|
1479
|
-
console.log(stderr);
|
1480
|
-
} else {
|
1481
|
-
// Look for the PNG file.
|
1482
|
-
const mode = fs.constants.R_OK | fs.constants.W_O;
|
1483
|
-
try {
|
1484
|
-
fs.accessSync(fp + '.png', mode);
|
1485
|
-
ext = '.png';
|
1486
|
-
} catch(err) {
|
1487
|
-
// NOTE: Inkscape 1.3 adds ".png" to the original file name,
|
1488
|
-
// so this may end on ".svg.png"
|
1489
|
-
try {
|
1490
|
-
fs.accessSync(fp + '.svg.png', mode);
|
1491
|
-
// If found, rename the PNG file.
|
1492
|
-
fs.renameSync(fp + '.svg.png', fp + '.png');
|
1493
|
-
ext = '.png';
|
1494
|
-
} catch(err) {
|
1495
|
-
console.log('WARNING: Inkscape did not output a PNG file');
|
1496
|
-
}
|
1497
|
-
}
|
1498
|
-
// Delete the SVG file.
|
1499
|
-
try {
|
1500
|
-
fs.unlinkSync(fp + '.svg');
|
1501
|
-
} catch(error) {
|
1502
|
-
console.log(`NOTICE: Failed to delete SVG file "${fp}.svg"`);
|
1503
|
-
}
|
1504
|
-
}
|
1505
|
-
// Return the image file name (PNG if successful, otherwise SVG)
|
1506
|
-
servePlainText(res, 'diagrams/' + fn + ext);
|
1507
|
-
}
|
1508
|
-
);
|
1509
|
-
} else {
|
1510
|
-
servePlainText(res, 'diagrams/' + fn + '.svg');
|
1511
|
-
}
|
1512
|
-
}
|
1513
|
-
|
1514
1437
|
// Convenience functions to fetch data from external URL
|
1515
1438
|
// NOTE: the parameters `on_ok` and `on_error` must be functions with two
|
1516
1439
|
// parameters:
|
@@ -1591,8 +1514,6 @@ function commandLineSettings() {
|
|
1591
1514
|
// Sets default settings, and then checks the command line arguments.
|
1592
1515
|
const settings = {
|
1593
1516
|
cli_name: (PLATFORM.startsWith('win') ? 'Command Prompt' : 'Terminal'),
|
1594
|
-
inkscape: '',
|
1595
|
-
dpi: 300,
|
1596
1517
|
launch: false,
|
1597
1518
|
port: 5050,
|
1598
1519
|
preferred_solver: '',
|
@@ -1604,7 +1525,6 @@ function commandLineSettings() {
|
|
1604
1525
|
usage = `Usage: ${app} server [options]
|
1605
1526
|
|
1606
1527
|
Possible options are:
|
1607
|
-
dpi=[number] will make InkScape render SVGs in the specified resolution
|
1608
1528
|
help will display these command line options
|
1609
1529
|
launch will open the Linny-R GUI in a browser window
|
1610
1530
|
port=[number] will listen at the specified port number
|
@@ -1635,14 +1555,6 @@ Possible options are:
|
|
1635
1555
|
} else {
|
1636
1556
|
settings.preferred_solver = av[1];
|
1637
1557
|
}
|
1638
|
-
} else if(av[0] === 'dpi') {
|
1639
|
-
// Accept any number greater than or equal to 1024.
|
1640
|
-
const n = parseInt(av[1]);
|
1641
|
-
if(isNaN(n) || n > 1200) {
|
1642
|
-
console.log(`WARNING: Invalid resolution ${av[1]} (max. 1200 dpi)`);
|
1643
|
-
} else {
|
1644
|
-
settings.dpi = n;
|
1645
|
-
}
|
1646
1558
|
} else if(av[0] === 'workspace') {
|
1647
1559
|
// User directory must be READ/WRITE-accessible.
|
1648
1560
|
try {
|
@@ -1665,55 +1577,6 @@ Possible options are:
|
|
1665
1577
|
}
|
1666
1578
|
}
|
1667
1579
|
}
|
1668
|
-
// Check whether Inkscape has been installed.
|
1669
|
-
const path_list = process.env.PATH.split(path.delimiter);
|
1670
|
-
for(let i = 0; i < path_list.length; i++) {
|
1671
|
-
// Check whether it is an Inkscape path.
|
1672
|
-
match = path_list[i].match(/inkscape/i);
|
1673
|
-
// If so, use it (so the *last* matching path will be used).
|
1674
|
-
if(match) settings.inkscape = path_list[i];
|
1675
|
-
}
|
1676
|
-
// NOTE: On macOS, Inkscape is not added to the PATH environment variable.
|
1677
|
-
if(!settings.inkscape && PLATFORM === 'darwin') {
|
1678
|
-
console.log('Looking for Inkscape in Applications...');
|
1679
|
-
try {
|
1680
|
-
// Look in the default directory.
|
1681
|
-
const ip = '/Applications/Inkscape.app/Contents/MacOS';
|
1682
|
-
fs.accessSync(ip);
|
1683
|
-
settings.inkscape = ip;
|
1684
|
-
} catch(err) {
|
1685
|
-
// No real error, so no action needed.
|
1686
|
-
}
|
1687
|
-
}
|
1688
|
-
// Verify that Inkscape is installed.
|
1689
|
-
if(settings.inkscape) {
|
1690
|
-
// NOTE: On Windows, the command line version is a .com file.
|
1691
|
-
let ip = path.join(settings.inkscape,
|
1692
|
-
'inkscape' + (PLATFORM.startsWith('win') ? '.com' : ''));
|
1693
|
-
try {
|
1694
|
-
fs.accessSync(ip, fs.constants.X_OK);
|
1695
|
-
} catch(err) {
|
1696
|
-
// NOTE: As of Inkscape version 1.3, the command line executable
|
1697
|
-
// is called inkscapecom(.com).
|
1698
|
-
ip = path.join(settings.inkscape,
|
1699
|
-
'inkscapecom' + (PLATFORM.startsWith('win') ? '.com' : ''));
|
1700
|
-
}
|
1701
|
-
try {
|
1702
|
-
fs.accessSync(ip, fs.constants.X_OK);
|
1703
|
-
console.log('Path to Inkscape:', settings.inkscape);
|
1704
|
-
settings.inkscape = ip;
|
1705
|
-
console.log(
|
1706
|
-
`SVG will be rendered with ${settings.dpi} dpi resolution`);
|
1707
|
-
} catch(err) {
|
1708
|
-
settings.inkscape = '';
|
1709
|
-
console.log(err.message);
|
1710
|
-
console.log(
|
1711
|
-
'WARNING: Failed to access the Inkscape command line application');
|
1712
|
-
}
|
1713
|
-
} else {
|
1714
|
-
console.log(
|
1715
|
-
'Inkscape not installed, so images will not be rendered as PNG');
|
1716
|
-
}
|
1717
1580
|
return settings;
|
1718
1581
|
}
|
1719
1582
|
|
@@ -1741,7 +1604,6 @@ function createWorkspace() {
|
|
1741
1604
|
channel: path.join(SETTINGS.user_dir, 'channel'),
|
1742
1605
|
callback: path.join(SETTINGS.user_dir, 'callback'),
|
1743
1606
|
data: path.join(SETTINGS.user_dir, 'data'),
|
1744
|
-
diagrams: path.join(SETTINGS.user_dir, 'diagrams'),
|
1745
1607
|
models: path.join(SETTINGS.user_dir, 'models'),
|
1746
1608
|
modules: path.join(SETTINGS.user_dir, 'modules'),
|
1747
1609
|
reports: path.join(SETTINGS.user_dir, 'reports'),
|
package/static/index.html
CHANGED
@@ -277,13 +277,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
277
277
|
title="Sensitivity analysis (Ctrl-J)">
|
278
278
|
<img id="experiment-btn" class="btn enab" src="images/experiment.png"
|
279
279
|
title="Manage experiments (Ctrl-X)">
|
280
|
-
<a href="show-png.html" target="_blank"
|
281
|
-
style="text-decoration: none; outline: none">
|
282
|
-
<img id="diagram-btn" class="btn enab" src="images/diagram.png"
|
283
|
-
title="Render diagram as bitmap at 300 dpi (Ctrl-P)">
|
284
|
-
</a>
|
285
280
|
<img id="savediagram-btn" class="btn enab" src="images/save-diagram.png"
|
286
|
-
title="Download diagram as
|
281
|
+
title="Download diagram as Portable Network Graphics bitmap image (Ctrl-P)
|
282
|
+
✎ Shift-click to download as Scalable Vector Graphics (Ctrl-Shift-P)">
|
287
283
|
<img id="finder-btn" class="btn enab" src="images/find.png"
|
288
284
|
title="Find model elements by their name (Ctrl-F)">
|
289
285
|
<img id="monitor-btn" class="btn enab" src="images/monitor.png"
|
@@ -771,6 +767,24 @@ NOTE: Unit symbols are case-sensitive, so BTU ≠ Btu">
|
|
771
767
|
<table id="power-grids-table">
|
772
768
|
</table>
|
773
769
|
</div>
|
770
|
+
<table>
|
771
|
+
<tr title="Checked aspects will be ignored for all power grids">
|
772
|
+
<td style="padding-bottom: 3px; font-style: italic">Disregard:</td>
|
773
|
+
<td style="padding: 0px; width: 20px">
|
774
|
+
<div id="power-grids-capacity" class="box clear"></div>
|
775
|
+
</td>
|
776
|
+
<td style="padding-bottom: 3px; width: 70px">Congestion</td>
|
777
|
+
<td style="padding: 0px; width: 20px">
|
778
|
+
<div id="power-grids-KVL" class="box clear"></div>
|
779
|
+
</td>
|
780
|
+
<td style="padding-bottom: 3px; width: 35px"
|
781
|
+
title="Kirchhoff's Voltage Law">KVL</td>
|
782
|
+
<td style="padding: 0px; width: 20px">
|
783
|
+
<div id="power-grids-losses" class="box clear"></div>
|
784
|
+
</td>
|
785
|
+
<td style="padding-bottom: 3px">Losses</td>
|
786
|
+
</tr>
|
787
|
+
</table>
|
774
788
|
</div>
|
775
789
|
</div>
|
776
790
|
|
@@ -1843,6 +1857,8 @@ Each line should represent the points of a different bound line.">
|
|
1843
1857
|
title="Rename selected dataset">
|
1844
1858
|
<img id="ds-clone-btn" class="btn disab" src="images/clone.png"
|
1845
1859
|
title="Clone selected dataset">
|
1860
|
+
<img id="ds-load-btn" class="btn enab" src="images/open.png"
|
1861
|
+
title="Load dataset(s) from CSV file">
|
1846
1862
|
<img id="ds-delete-btn" class="btn disab" src="images/delete.png"
|
1847
1863
|
title="Delete selected dataset"
|
1848
1864
|
style="position: absolute; right: 2px">
|
@@ -1940,6 +1956,19 @@ Start with = to find exact match, with ~ to match first characters">
|
|
1940
1956
|
<input id="rename-dataset-name" type="text" autocomplete="off">
|
1941
1957
|
</div>
|
1942
1958
|
</div>
|
1959
|
+
|
1960
|
+
<!-- the LOAD CSV dialog prompts the user for a CSV file on disk
|
1961
|
+
to be loaded -->
|
1962
|
+
<div id="load-csv-modal" class="modal">
|
1963
|
+
<div id="load-csv-dlg" class="inp-dlg">
|
1964
|
+
<div class="dlg-title">
|
1965
|
+
Load datasets from CSV file
|
1966
|
+
<img class="cancel-btn" src="images/cancel.png">
|
1967
|
+
<img class="ok-btn" src="images/ok.png">
|
1968
|
+
</div>
|
1969
|
+
<input id="load-csv-file" type="file">
|
1970
|
+
</div>
|
1971
|
+
</div>
|
1943
1972
|
|
1944
1973
|
<!-- the NEW SELECTOR dialog prompts for a new selector for a dataset -->
|
1945
1974
|
<div id="new-selector-modal" class="modal">
|
@@ -2219,13 +2248,8 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
2219
2248
|
</div>
|
2220
2249
|
<div id="chart-only-buttons">
|
2221
2250
|
<img id="chart-save-btn" class="btn enab" src="images/save-chart.png"
|
2222
|
-
title="
|
2223
|
-
|
2224
|
-
style="margin-left: 4px; text-decoration: none; outline: none">
|
2225
|
-
<img class="btn enab" src="images/chart.png"
|
2226
|
-
title="Render chart diagram as PNG"
|
2227
|
-
style="height: 20px; width: 20px">
|
2228
|
-
</a>
|
2251
|
+
title="Download chart as bitmap image (PNG)
|
2252
|
+
✎ Shift-click to download chart as Scalable Vector Graphics (SVG)">
|
2229
2253
|
<img id="chart-widen-btn" class="btn enab" src="images/stretch.png"
|
2230
2254
|
title="Widen chart" style="margin-left: 24px">
|
2231
2255
|
<img id="chart-narrow-btn" class="btn enab" src="images/compress.png"
|
@@ -2495,7 +2519,7 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
2495
2519
|
<div id="experiment-separator"></div>
|
2496
2520
|
<div id="experiment-default-message">
|
2497
2521
|
To define a meaningful experiment, a model must feature at least
|
2498
|
-
one outcome dataset, or a
|
2522
|
+
one outcome dataset, or a chart having one or more variables.
|
2499
2523
|
</div>
|
2500
2524
|
<div id="experiment-params-header">(no experiment selected)</div>
|
2501
2525
|
<div id="experiment-params-div">
|
@@ -2843,7 +2867,9 @@ NOTE: * and ? will be interpreted as wildcards"
|
|
2843
2867
|
<label>Settings:</label>
|
2844
2868
|
<input id="xp-settings-selector-string" type="text" autocomplete="off"
|
2845
2869
|
title="Can specifiy time step, simulation period, block length and look-ahead.
|
2846
|
-
Example: s=0.5h t=1-480 b=24 l=24
|
2870
|
+
Example: s=0.5h t=1-480 b=24 l=24
|
2871
|
+
When modeling power grids, -c indicates “disregard grid capacity”,
|
2872
|
+
-k “disregard Kirchhoff's Voltage Law”, and -l “disregard power losses”">
|
2847
2873
|
</div>
|
2848
2874
|
</div>
|
2849
2875
|
</div>
|
@@ -3033,12 +3059,17 @@ where X can be one or several of these letters: ABCDELPQ">
|
|
3033
3059
|
<div id="finder-status">
|
3034
3060
|
<span id="finder-count"></span> found
|
3035
3061
|
</div>
|
3036
|
-
<
|
3037
|
-
|
3038
|
-
|
3039
|
-
|
3040
|
-
|
3041
|
-
|
3062
|
+
<div id="finder-status-buttons">
|
3063
|
+
<img id="finder-edit-btn" class="btn enab"
|
3064
|
+
src="images/edit.png"
|
3065
|
+
title="Edit attributes">
|
3066
|
+
<img id="finder-chart-btn" class="btn enab"
|
3067
|
+
src="images/chart.png"
|
3068
|
+
title="Add attribute to chart">
|
3069
|
+
<img id="finder-copy-btn" class="btn enab"
|
3070
|
+
src="images/table-to-clpbrd.png"
|
3071
|
+
title="Copy entity attributes to clipboard">
|
3072
|
+
</div>
|
3042
3073
|
<div id="finder-separator"></div>
|
3043
3074
|
<div id="finder-item-header">(no item selected)</div>
|
3044
3075
|
<div id="finder-item-scroll-area">
|
@@ -3053,6 +3084,28 @@ where X can be one or several of these letters: ABCDELPQ">
|
|
3053
3084
|
<div id="finder-resize" class="resizer"></div>
|
3054
3085
|
</div>
|
3055
3086
|
|
3087
|
+
<!-- the CONFIRM ADD CHART VARIABLES modal asks to confirm to add a
|
3088
|
+
specific attribute of the filtered entities to the current chart -->
|
3089
|
+
<div id="confirm-add-chart-variables-modal" class="modal">
|
3090
|
+
<div id="confirm-add-chart-variables-dlg" class="inp-dlg">
|
3091
|
+
<div class="dlg-title">
|
3092
|
+
Add to chart
|
3093
|
+
<img class="cancel-btn" src="images/cancel.png">
|
3094
|
+
<img class="ok-btn" src="images/ok.png">
|
3095
|
+
</div>
|
3096
|
+
<div style="margin: 2px; padding-right: 2px; white-space: nowrap">
|
3097
|
+
<select id="confirm-add-chart-variables-attribute"></select>
|
3098
|
+
of <span id="confirm-add-chart-variables-count"></span>
|
3099
|
+
</div>
|
3100
|
+
<div>
|
3101
|
+
<div id="confirm-add-chart-variables-stacked" class="box clear"></div>
|
3102
|
+
<div style="display:inline-block; vertical-align:top; margin-top: 3px">
|
3103
|
+
Display as stacked areas
|
3104
|
+
</div>
|
3105
|
+
</div>
|
3106
|
+
</div>
|
3107
|
+
</div>
|
3108
|
+
|
3056
3109
|
<!-- the MONITOR dialog shows solver progress and messages, and model equations -->
|
3057
3110
|
<div id="monitor-dlg" class="inp-dlg">
|
3058
3111
|
<div id="monitor-hdr" class="dragger dlg-title">Solver monitor
|
package/static/linny-r.css
CHANGED
@@ -794,6 +794,7 @@ div.checked.not-same-not-changed {
|
|
794
794
|
|
795
795
|
/* LOAD modal dialog */
|
796
796
|
#load-dlg,
|
797
|
+
#load-csv-dlg,
|
797
798
|
#comparison-dlg {
|
798
799
|
width: 430px;
|
799
800
|
height: min-content;
|
@@ -801,6 +802,7 @@ div.checked.not-same-not-changed {
|
|
801
802
|
}
|
802
803
|
|
803
804
|
#load-xml-file,
|
805
|
+
#load-csv-file,
|
804
806
|
#comparison-xml-file {
|
805
807
|
padding: 2px;
|
806
808
|
max-width: 375px;
|
@@ -1063,7 +1065,7 @@ div.grid-watts {
|
|
1063
1065
|
margin-right: 3px;
|
1064
1066
|
}
|
1065
1067
|
|
1066
|
-
div.grid-
|
1068
|
+
div.grid-kvl-symbol {
|
1067
1069
|
display: inline-block;
|
1068
1070
|
height: 17px;
|
1069
1071
|
font-size: 19px;
|
@@ -5032,24 +5034,20 @@ img.finder {
|
|
5032
5034
|
width: 50%;
|
5033
5035
|
}
|
5034
5036
|
|
5035
|
-
|
5036
|
-
|
5037
|
-
#finder-edit-btn {
|
5037
|
+
#finder-status-buttons {
|
5038
5038
|
position: absolute;
|
5039
|
-
|
5040
|
-
|
5041
|
-
bottom: 1px;
|
5042
|
-
right: calc(50% + 24px);
|
5043
|
-
display: none;
|
5039
|
+
bottom: 0px;
|
5040
|
+
right: calc(50% + 1px);
|
5044
5041
|
}
|
5045
5042
|
|
5043
|
+
/* NOTE: Finder buttons are initially invisible */
|
5044
|
+
|
5045
|
+
#finder-edit-btn,
|
5046
|
+
#finder-chart-btn,
|
5046
5047
|
#finder-copy-btn {
|
5047
|
-
|
5048
|
-
|
5049
|
-
|
5050
|
-
bottom: 1px;
|
5051
|
-
right: calc(50% + 1px);
|
5052
|
-
display: none; /* NOTE: button is initially invisible */
|
5048
|
+
height: 15px;
|
5049
|
+
width: 15px;
|
5050
|
+
display: none;
|
5053
5051
|
}
|
5054
5052
|
|
5055
5053
|
#finder-separator {
|
@@ -5097,6 +5095,14 @@ img.finder {
|
|
5097
5095
|
border-top: 1px solid Silver;
|
5098
5096
|
}
|
5099
5097
|
|
5098
|
+
#confirm-add-chart-variables-dlg {
|
5099
|
+
width: min-content;
|
5100
|
+
height: min-content;
|
5101
|
+
}
|
5102
|
+
|
5103
|
+
#confirm-add-chart-variables-attribute {
|
5104
|
+
font-size: 12px;
|
5105
|
+
}
|
5100
5106
|
|
5101
5107
|
/* the MONITOR DIALOG displays solver progress and messages */
|
5102
5108
|
#monitor-dlg {
|
@@ -5302,7 +5308,7 @@ div.sel-tab {
|
|
5302
5308
|
z-index: 150; /* should be highest of all dialogs (even modal ones) */
|
5303
5309
|
margin: 0;
|
5304
5310
|
width: 395px;
|
5305
|
-
height:
|
5311
|
+
height: 200px;
|
5306
5312
|
min-width: 340px;
|
5307
5313
|
min-height: 150px;
|
5308
5314
|
max-height: 99vh;
|