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
@@ -225,6 +225,13 @@ function ellipsedText(text, n=50, m=10) {
|
|
225
225
|
return text.slice(0, n) + ' \u2026 ' + text.slice(text.length - m);
|
226
226
|
}
|
227
227
|
|
228
|
+
function unquoteCSV(s) {
|
229
|
+
// Returns a double-quoted string `s` without its quotes, and with
|
230
|
+
// quote pairs "" replaced by single " quotes.
|
231
|
+
if(!s.startsWith('"') || !s.endsWith('"')) return s;
|
232
|
+
return s.slice(1, -1).replaceAll('""', '"');
|
233
|
+
}
|
234
|
+
|
228
235
|
//
|
229
236
|
// Functions used when comparing two Linny-R models
|
230
237
|
//
|
@@ -535,8 +542,8 @@ function matchingNumber(m, s) {
|
|
535
542
|
function matchingNumberInList(ml, s) {
|
536
543
|
// Traverses list `ml` and returns the first matching number, or FALSE
|
537
544
|
// if no match is found.
|
538
|
-
for(
|
539
|
-
const n = matchingNumber(
|
545
|
+
for(const m of ml) {
|
546
|
+
const n = matchingNumber(m, s);
|
540
547
|
if(n !== false) return n;
|
541
548
|
}
|
542
549
|
return false;
|
@@ -673,19 +680,17 @@ function compareCombinations(c1, c2) {
|
|
673
680
|
//
|
674
681
|
|
675
682
|
function addDistinct(e, list) {
|
676
|
-
//
|
683
|
+
// Add element `e` to `list` only if it does not already occur in `list`.
|
677
684
|
if(list.indexOf(e) < 0) list.push(e);
|
678
685
|
}
|
679
686
|
|
680
687
|
function mergeDistinct(list, into) {
|
681
|
-
//
|
682
|
-
for(
|
683
|
-
addDistinct(list[i], into);
|
684
|
-
}
|
688
|
+
// Add elements of `list` to `into` if not already in `into`.
|
689
|
+
for(const e of list) addDistinct(e, into);
|
685
690
|
}
|
686
691
|
|
687
692
|
function iteratorSet(list) {
|
688
|
-
//
|
693
|
+
// Return TRUE iff list is something like ['i=1', 'i=2', 'i=3'].
|
689
694
|
if(list.length === 0) return false;
|
690
695
|
// Analyze the first element: must start with i=, j= or k=.
|
691
696
|
const
|
@@ -715,9 +720,7 @@ function iteratorSet(list) {
|
|
715
720
|
function integerSet(list) {
|
716
721
|
// Returns TRUE iff all elements in list evaluate as integer numbers.
|
717
722
|
if(list.length === 0) return false;
|
718
|
-
for(
|
719
|
-
if(list[i] - 0 != list[i]) return false;
|
720
|
-
}
|
723
|
+
for(const n of list) if(n - 0 != n) return false;
|
721
724
|
return true;
|
722
725
|
}
|
723
726
|
|
@@ -750,20 +753,18 @@ function tupelString(sl) {
|
|
750
753
|
}
|
751
754
|
|
752
755
|
function tupelSetString(ssl) {
|
753
|
-
//
|
756
|
+
// Return string of stringlists `sll` as set of tuples.
|
754
757
|
const tl = [];
|
755
|
-
for(
|
756
|
-
tl.push(tupelString(ssl[i]));
|
757
|
-
}
|
758
|
+
for(const ss of ssl) tl.push(tupelString(ss));
|
758
759
|
return setString(tl);
|
759
760
|
}
|
760
761
|
|
761
762
|
function tupelIndex(sl, ssl) {
|
762
|
-
//
|
763
|
+
// Return index of stringlist `sl` if it exists in `ssl`, otherwise -1.
|
763
764
|
for(let i = 0; i < ssl.length; i++) {
|
764
765
|
let n = 0;
|
765
|
-
for(
|
766
|
-
if(ssl[i].indexOf(
|
766
|
+
for(const s of sl) {
|
767
|
+
if(ssl[i].indexOf(s) < 0) break;
|
767
768
|
n++;
|
768
769
|
}
|
769
770
|
if(n == sl.length) return i;
|
@@ -772,20 +773,16 @@ function tupelIndex(sl, ssl) {
|
|
772
773
|
}
|
773
774
|
|
774
775
|
function intersection(sl1, sl2) {
|
775
|
-
//
|
776
|
+
// Return the list of common elements of stringlists `l1` and `l2`.
|
776
777
|
const shared = [];
|
777
|
-
for(
|
778
|
-
if(sl2.indexOf(sl1[i]) >= 0) shared.push(sl1[i]);
|
779
|
-
}
|
778
|
+
for(const s of sl1) if(sl2.indexOf(s) >= 0) shared.push(s);
|
780
779
|
return shared;
|
781
780
|
}
|
782
781
|
|
783
782
|
function complement(sl1, sl2) {
|
784
783
|
// Returns the list of elements of stringlist `l1` that are NOT in `l2`
|
785
784
|
const cmplmnt = [];
|
786
|
-
for(
|
787
|
-
if(sl2.indexOf(sl1[i]) < 0) cmplmnt.push(sl1[i]);
|
788
|
-
}
|
785
|
+
for(const s of sl1) if(sl2.indexOf(s) < 0) cmplmnt.push(s);
|
789
786
|
return cmplmnt;
|
790
787
|
}
|
791
788
|
|
@@ -793,6 +790,15 @@ function complement(sl1, sl2) {
|
|
793
790
|
// Functions that support loading and saving data and models
|
794
791
|
//
|
795
792
|
|
793
|
+
function asFileName(s) {
|
794
|
+
// Return string `s` with whitespace converted to a single dash, and
|
795
|
+
// special characters converted to underscores.
|
796
|
+
return s.normalize('NFKD').trim()
|
797
|
+
.replace(/[\s\-]+/g, '-')
|
798
|
+
.replace(/[^A-Za-z0-9_\-]/g, '_')
|
799
|
+
.replace(/^[\-\_]+|[\-\_]+$/g, '');
|
800
|
+
}
|
801
|
+
|
796
802
|
function xmlEncoded(str) {
|
797
803
|
// Replaces &, <, >, ' and " by their HTML entity code
|
798
804
|
return str.replace(/\&/g, '&').replace(/</g, '<'
|
@@ -836,8 +842,8 @@ function customizeXML(str) {
|
|
836
842
|
}
|
837
843
|
|
838
844
|
function cleanXML(node) {
|
839
|
-
//
|
840
|
-
// subtree under node
|
845
|
+
// Remove all unnamed text nodes and comment nodes from the XML
|
846
|
+
// subtree under node.
|
841
847
|
const cn = node.childNodes;
|
842
848
|
if(cn) {
|
843
849
|
for(let i = cn.length - 1; i >= 0; i--) {
|
@@ -1132,6 +1138,7 @@ if(NODE) module.exports = {
|
|
1132
1138
|
uniformDecimals: uniformDecimals,
|
1133
1139
|
capitalized: capitalized,
|
1134
1140
|
ellipsedText: ellipsedText,
|
1141
|
+
unquoteCSV: unquoteCSV,
|
1135
1142
|
earlierVersion: earlierVersion,
|
1136
1143
|
differences: differences,
|
1137
1144
|
markFirstDifference: markFirstDifference,
|
@@ -1161,6 +1168,7 @@ if(NODE) module.exports = {
|
|
1161
1168
|
tupelIndex: tupelIndex,
|
1162
1169
|
intersection: intersection,
|
1163
1170
|
complement: complement,
|
1171
|
+
asFileName: asFileName,
|
1164
1172
|
xmlEncoded: xmlEncoded,
|
1165
1173
|
xmlDecoded: xmlDecoded,
|
1166
1174
|
customizeXML: customizeXML,
|