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
@@ -301,18 +301,16 @@ class GUIExperimentManager extends ExperimentManager {
|
|
301
301
|
xl = [],
|
302
302
|
xtl = [],
|
303
303
|
sx = this.selected_experiment;
|
304
|
-
for(
|
305
|
-
xtl.push(MODEL.experiments[i].title);
|
306
|
-
}
|
304
|
+
for(const x of MODEL.experiments) xtl.push(x.title);
|
307
305
|
xtl.sort(ciCompare);
|
308
|
-
for(
|
306
|
+
for(const xt of xtl) {
|
309
307
|
const
|
310
|
-
xi = MODEL.indexOfExperiment(
|
308
|
+
xi = MODEL.indexOfExperiment(xt),
|
311
309
|
x = (xi < 0 ? null : MODEL.experiments[xi]);
|
312
310
|
xl.push(['<tr class="experiment',
|
313
311
|
(x == sx ? ' sel-set' : ''),
|
314
312
|
'" onclick="EXPERIMENT_MANAGER.selectExperiment(\'',
|
315
|
-
escapedSingleQuotes(
|
313
|
+
escapedSingleQuotes(xt),
|
316
314
|
'\');" onmouseover="EXPERIMENT_MANAGER.showInfo(', xi,
|
317
315
|
', event.shiftKey);"><td>', x.title, '</td></tr>'].join(''));
|
318
316
|
}
|
@@ -369,9 +367,7 @@ class GUIExperimentManager extends ExperimentManager {
|
|
369
367
|
dim_count.innerHTML = pluralS(x.available_dimensions.length,
|
370
368
|
'more dimension');
|
371
369
|
x.inferActualDimensions();
|
372
|
-
for(
|
373
|
-
x.actual_dimensions[i].sort(compareSelectors);
|
374
|
-
}
|
370
|
+
for(const ad of x.actual_dimensions) ad.sort(compareSelectors);
|
375
371
|
x.inferCombinations();
|
376
372
|
//x.combinations.sort(compareCombinations);
|
377
373
|
combi_count.innerHTML = pluralS(x.combinations.length, 'combination');
|
@@ -532,9 +528,9 @@ class GUIExperimentManager extends ExperimentManager {
|
|
532
528
|
ol = [],
|
533
529
|
ov = MODEL.outcomeNames,
|
534
530
|
vl = [...ov];
|
535
|
-
for(
|
531
|
+
for(const v of x.variables) {
|
536
532
|
const
|
537
|
-
vn =
|
533
|
+
vn = v.displayName,
|
538
534
|
oi = ov.indexOf(vn);
|
539
535
|
// If an outcome dataset or equation is plotted in an experiment
|
540
536
|
// chart, remove its name from the outcome variable list.
|
@@ -546,8 +542,7 @@ class GUIExperimentManager extends ExperimentManager {
|
|
546
542
|
// name will not be in the list (and its old name cannot be inferred)
|
547
543
|
// so then clear it.
|
548
544
|
if(vl.indexOf(x.selected_variable) < 0) x.selected_variable = '';
|
549
|
-
for(
|
550
|
-
const vn = vl[i];
|
545
|
+
for(const vn of vl) {
|
551
546
|
// NOTE: FireFox selector dropdown areas have a pale gray
|
552
547
|
// background that darkens when color is set, so always set it
|
553
548
|
// to white (like Chrome). Then set color of outcome variables
|
@@ -565,12 +560,12 @@ class GUIExperimentManager extends ExperimentManager {
|
|
565
560
|
}
|
566
561
|
|
567
562
|
drawTable() {
|
568
|
-
// Draw experimental design as table
|
563
|
+
// Draw experimental design as table.
|
569
564
|
const x = this.selected_experiment;
|
570
565
|
if(x) {
|
571
566
|
this.clean_columns = [];
|
572
567
|
this.clean_rows = [];
|
573
|
-
// Calculate the actual number of columns and rows of the table
|
568
|
+
// Calculate the actual number of columns and rows of the table.
|
574
569
|
const
|
575
570
|
coldims = x.configuration_dims + x.column_scenario_dims,
|
576
571
|
rowdims = x.actual_dimensions.length - coldims,
|
@@ -795,32 +790,28 @@ class GUIExperimentManager extends ExperimentManager {
|
|
795
790
|
const combi = x.combinations[n];
|
796
791
|
info.title = `Combination: <tt>${tupelString(combi)}</tt>`;
|
797
792
|
const html = [], list = [];
|
798
|
-
for(
|
799
|
-
const sel = combi[i];
|
793
|
+
for(const sel of combi) {
|
800
794
|
html.push('<h3>Selector <tt>', sel, '</tt></h3>');
|
801
|
-
// List associated model settings (if any)
|
795
|
+
// List associated model settings (if any).
|
802
796
|
list.length = 0;
|
803
|
-
for(
|
804
|
-
const
|
805
|
-
if(sel ===
|
797
|
+
for(const ss of x.settings_selectors) {
|
798
|
+
const tuple = ss.split('|');
|
799
|
+
if(sel === tuple[0]) list.push(tuple[1]);
|
806
800
|
}
|
807
801
|
if(list.length > 0) {
|
808
802
|
html.push('<p><em>Model settings:</em> <tt>', list.join(';'),
|
809
803
|
'</tt></p>');
|
810
804
|
}
|
811
|
-
// List associated actor settings (if any)
|
805
|
+
// List associated actor settings (if any).
|
812
806
|
list.length = 0;
|
813
|
-
for(
|
814
|
-
|
815
|
-
if(sel === as.selector) {
|
816
|
-
list.push(as.round_sequence);
|
817
|
-
}
|
807
|
+
for(const as of x.actor_selectors) {
|
808
|
+
if(sel === as.selector) list.push(as.round_sequence);
|
818
809
|
}
|
819
810
|
if(list.length > 0) {
|
820
811
|
html.push('<p><em>Actor settings:</em> <tt>', list.join(';'),
|
821
812
|
'</tt></p>');
|
822
813
|
}
|
823
|
-
// List associated datasets (if any)
|
814
|
+
// List associated datasets (if any).
|
824
815
|
list.length = 0;
|
825
816
|
for(let id in MODEL.datasets) if(MODEL.datasets.hasOwnProperty(id)) {
|
826
817
|
const ds = MODEL.datasets[id];
|
@@ -888,10 +879,8 @@ class GUIExperimentManager extends ExperimentManager {
|
|
888
879
|
// Set reference column indices so that values for the reference|
|
889
880
|
// configuration can be displayed in orange.
|
890
881
|
const ref_conf_indices = [];
|
891
|
-
for(
|
892
|
-
const
|
893
|
-
r = x.runs[i],
|
894
|
-
rr = r.results[rri];
|
882
|
+
for(const r of x.runs) {
|
883
|
+
const rr = r.results[rri];
|
895
884
|
if(!rr) {
|
896
885
|
data.push(VM.UNDEFINED);
|
897
886
|
} else if(x.selected_scale === 'sec') {
|
@@ -918,12 +907,12 @@ class GUIExperimentManager extends ExperimentManager {
|
|
918
907
|
}
|
919
908
|
// Scale data as selected.
|
920
909
|
const scaled = data.slice();
|
921
|
-
// NOTE:
|
922
|
-
// configurations have been defined (otherwise comparison is pointless)
|
910
|
+
// NOTE: Scale only after the experiment has been completed AND
|
911
|
+
// configurations have been defined (otherwise comparison is pointless).
|
923
912
|
if(x.completed && this.nr_of_configurations > 0) {
|
924
913
|
const n = scaled.length / this.nr_of_configurations;
|
925
914
|
if(x.selected_scale === 'dif') {
|
926
|
-
// Compute difference: current configuration - reference configuration
|
915
|
+
// Compute difference: current configuration - reference configuration.
|
927
916
|
const rc = x.reference_configuration;
|
928
917
|
for(let i = 0; i < this.nr_of_configurations; i++) {
|
929
918
|
if(i != rc) {
|
@@ -932,47 +921,36 @@ class GUIExperimentManager extends ExperimentManager {
|
|
932
921
|
}
|
933
922
|
}
|
934
923
|
}
|
935
|
-
// Set difference for reference configuration itself to 0
|
924
|
+
// Set difference for reference configuration itself to 0.
|
936
925
|
for(let i = 0; i < n; i++) {
|
937
926
|
const index = rc * n + i;
|
938
927
|
scaled[index] = 0;
|
939
928
|
ref_conf_indices.push(index);
|
940
929
|
}
|
941
930
|
} else if(x.selected_scale === 'reg') {
|
942
|
-
// Compute regret: current config - high value config in same scenario
|
931
|
+
// Compute regret: current config - high value config in same scenario.
|
943
932
|
for(let i = 0; i < n; i++) {
|
944
|
-
// Get high value
|
933
|
+
// Get high value.
|
945
934
|
let high = VM.MINUS_INFINITY;
|
946
935
|
for(let j = 0; j < this.nr_of_configurations; j++) {
|
947
936
|
high = Math.max(high, scaled[j * n + i]);
|
948
937
|
}
|
949
|
-
// Scale (so high config always has value 0)
|
938
|
+
// Scale (so high config always has value 0).
|
950
939
|
for(let j = 0; j < this.nr_of_configurations; j++) {
|
951
940
|
scaled[j * n + i] -= high;
|
952
941
|
}
|
953
942
|
}
|
954
943
|
}
|
955
944
|
}
|
956
|
-
// For color scales, compute normalized scores
|
957
|
-
|
958
|
-
high =
|
959
|
-
low =
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
//
|
965
|
-
const range = (high - low < VM.NEAR_ZERO ? 0 : high - low);
|
966
|
-
if(range > 0) {
|
967
|
-
for(let i = 0; i < normalized.length; i++) {
|
968
|
-
normalized[i] = (normalized[i] - low) / range;
|
969
|
-
}
|
970
|
-
}
|
971
|
-
// Format data such that they all have same number of decimals
|
972
|
-
let formatted = [];
|
973
|
-
for(let i = 0; i < scaled.length; i++) {
|
974
|
-
formatted.push(VM.sig4Dig(scaled[i]));
|
975
|
-
}
|
945
|
+
// For color scales, compute normalized scores.
|
946
|
+
const
|
947
|
+
high = Math.max(...scaled),
|
948
|
+
low = Math.min(...scaled),
|
949
|
+
// Avoid too small value ranges.
|
950
|
+
range = (high - low < VM.NEAR_ZERO ? 0 : high - low),
|
951
|
+
normalized = scaled.map((v) => range ? (v - low) / range : v),
|
952
|
+
formatted = scaled.map((v) => VM.sig4Dig(v));
|
953
|
+
// Format data such that they all have same number of decimals.
|
976
954
|
uniformDecimals(formatted);
|
977
955
|
// Display formatted data in cells.
|
978
956
|
for(let i = 0; i < x.combinations.length; i++) {
|
@@ -1072,11 +1050,11 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1072
1050
|
const
|
1073
1051
|
spl = this.viewer.getElementsByClassName('spin-plus'),
|
1074
1052
|
rem = (x.configuration_dims + x.column_scenario_dims < xdims);
|
1075
|
-
for(
|
1053
|
+
for(const sp of spl) {
|
1076
1054
|
if(rem) {
|
1077
|
-
|
1055
|
+
sp.classList.remove('no-spin');
|
1078
1056
|
} else {
|
1079
|
-
|
1057
|
+
sp.classList.add('no-spin');
|
1080
1058
|
}
|
1081
1059
|
}
|
1082
1060
|
if(dir != 0 ) this.drawTable();
|
@@ -1103,9 +1081,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1103
1081
|
x.selected_color_scale = cs;
|
1104
1082
|
this.color_scale.set(cs);
|
1105
1083
|
const csl = this.viewer.getElementsByClassName('color-scale');
|
1106
|
-
for(
|
1107
|
-
csl.item(i).classList.remove('sel-cs');
|
1108
|
-
}
|
1084
|
+
for(const cs of csl) cs.classList.remove('sel-cs');
|
1109
1085
|
document.getElementById(`xv-${cs}-scale`).classList.add('sel-cs');
|
1110
1086
|
}
|
1111
1087
|
this.updateData();
|
@@ -1189,14 +1165,14 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1189
1165
|
}
|
1190
1166
|
|
1191
1167
|
editIteratorRanges() {
|
1192
|
-
// Open dialog for editing iterator ranges
|
1168
|
+
// Open dialog for editing iterator ranges.
|
1193
1169
|
const
|
1194
1170
|
x = this.selected_experiment,
|
1195
1171
|
md = this.iterator_modal,
|
1196
1172
|
il = ['i', 'j', 'k'];
|
1197
1173
|
if(x) {
|
1198
1174
|
// NOTE: there are always 3 iterators (i, j k) so these have fixed
|
1199
|
-
// FROM and TO input fields in the dialog
|
1175
|
+
// FROM and TO input fields in the dialog.
|
1200
1176
|
for(let i = 0; i < 3; i++) {
|
1201
1177
|
const k = il[i];
|
1202
1178
|
md.element(k + '-from').value = x.iterator_ranges[i][0];
|
@@ -1211,8 +1187,8 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1211
1187
|
x = this.selected_experiment,
|
1212
1188
|
md = this.iterator_modal;
|
1213
1189
|
if(x) {
|
1214
|
-
// First validate all input fields (must be integer values)
|
1215
|
-
// NOTE:
|
1190
|
+
// First validate all input fields (must be integer values).
|
1191
|
+
// NOTE: Test using a copy so as not to overwrite values until OK.
|
1216
1192
|
const
|
1217
1193
|
il = ['i', 'j', 'k'],
|
1218
1194
|
ir = [[0, 0], [0, 0], [0, 0]],
|
@@ -1227,7 +1203,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1227
1203
|
t = el.value.trim() || '0';
|
1228
1204
|
if(t === '' || re.test(t)) el = null;
|
1229
1205
|
}
|
1230
|
-
// NULL value signals that field inputs are valid
|
1206
|
+
// NULL value signals that field inputs are valid.
|
1231
1207
|
if(el === null) {
|
1232
1208
|
ir[i] = [f, t];
|
1233
1209
|
} else {
|
@@ -1236,7 +1212,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1236
1212
|
return;
|
1237
1213
|
}
|
1238
1214
|
}
|
1239
|
-
// Input validated, so modify the iterator dimensions
|
1215
|
+
// Input validated, so modify the iterator dimensions.
|
1240
1216
|
x.iterator_ranges = ir;
|
1241
1217
|
this.updateDialog();
|
1242
1218
|
}
|
@@ -1244,17 +1220,17 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1244
1220
|
}
|
1245
1221
|
|
1246
1222
|
editSettingsDimensions() {
|
1247
|
-
// Open dialog for editing model settings dimensions
|
1223
|
+
// Open dialog for editing model settings dimensions.
|
1248
1224
|
const x = this.selected_experiment, rows = [];
|
1249
1225
|
if(x) {
|
1250
|
-
// Initialize selector list
|
1226
|
+
// Initialize selector list.
|
1251
1227
|
for(let i = 0; i < x.settings_selectors.length; i++) {
|
1252
1228
|
const sel = x.settings_selectors[i].split('|');
|
1253
1229
|
rows.push('<tr onclick="EXPERIMENT_MANAGER.editSettingsSelector(', i,
|
1254
1230
|
');"><td width="25%">', sel[0], '</td><td>', sel[1], '</td></tr>');
|
1255
1231
|
}
|
1256
1232
|
this.settings_modal.element('s-table').innerHTML = rows.join('');
|
1257
|
-
// Initialize combination list
|
1233
|
+
// Initialize combination list.
|
1258
1234
|
rows.length = 0;
|
1259
1235
|
for(let i = 0; i < x.settings_dimensions.length; i++) {
|
1260
1236
|
const dim = x.settings_dimensions[i];
|
@@ -1263,14 +1239,14 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1263
1239
|
}
|
1264
1240
|
this.settings_modal.element('d-table').innerHTML = rows.join('');
|
1265
1241
|
this.settings_modal.show();
|
1266
|
-
// NOTE:
|
1267
|
-
// otherwise remain visible while no longer relevant
|
1242
|
+
// NOTE: Clear infoline because dialog can generate warnings that would
|
1243
|
+
// otherwise remain visible while no longer relevant.
|
1268
1244
|
UI.setMessage('');
|
1269
1245
|
}
|
1270
1246
|
}
|
1271
1247
|
|
1272
1248
|
closeSettingsDimensions() {
|
1273
|
-
// Hide editor, and then update the experiment manager to reflect changes
|
1249
|
+
// Hide editor, and then update the experiment manager to reflect changes.
|
1274
1250
|
this.settings_modal.hide();
|
1275
1251
|
this.updateDialog();
|
1276
1252
|
}
|
@@ -1303,8 +1279,10 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1303
1279
|
md = this.settings_selector_modal,
|
1304
1280
|
sc = md.element('code'),
|
1305
1281
|
ss = md.element('string'),
|
1306
|
-
|
1307
|
-
|
1282
|
+
// NOTE: Simply remove invalid characters from selector, but accept
|
1283
|
+
// '=' here to permit associating settings with iterator selectors.
|
1284
|
+
code = sc.value.replace(/[^\w\+\-\%\=]/g, ''),
|
1285
|
+
value = ss.value.trim().toLowerCase().replace(',', '.'),
|
1308
1286
|
add = this.edited_selector_index < 0;
|
1309
1287
|
// Remove selector if either field has been cleared
|
1310
1288
|
if(code.length === 0 || value.length === 0) {
|
@@ -1312,7 +1290,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1312
1290
|
x.settings_selectors.splice(this.edited_selector_index, 1);
|
1313
1291
|
}
|
1314
1292
|
} else {
|
1315
|
-
// Check for uniqueness of code
|
1293
|
+
// Check for uniqueness of code.
|
1316
1294
|
for(let i = 0; i < x.settings_selectors.length; i++) {
|
1317
1295
|
// NOTE: ignore selector being edited, as this selector can be renamed
|
1318
1296
|
if(i != this.edited_selector_index &&
|
@@ -1323,7 +1301,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1323
1301
|
}
|
1324
1302
|
}
|
1325
1303
|
// Check for valid syntax -- canonical example: s=0.25h t=1-100 b=12 l=6
|
1326
|
-
const re = /^(s\=\d+(\.?\d+)?(yr?|wk?|d|h|m|min|s)\s+)?(t\=\d+(\-\d+)?\s+)?(b\=\d+\s+)?(l=\d+\s+)?$/i;
|
1304
|
+
const re = /^(s\=\d+(\.?\d+)?(yr?|wk?|d|h|m|min|s)\s+)?(t\=\d+(\-\d+)?\s+)?(b\=\d+\s+)?(l=\d+\s+)?(\-[ckl]+\s+)?$/i;
|
1327
1305
|
if(!re.test(value + ' ')) {
|
1328
1306
|
UI.warn(`Invalid settings "${value}"`);
|
1329
1307
|
ss.focus();
|
@@ -1560,40 +1538,37 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1560
1538
|
if(x) {
|
1561
1539
|
const
|
1562
1540
|
add = this.edited_combi_dimension_index < 0,
|
1563
|
-
// Trim whitespace and reduce inner spacing to a single space
|
1541
|
+
// Trim whitespace and reduce inner spacing to a single space.
|
1564
1542
|
dimstr = this.combination_dimension_modal.element('string').value.trim();
|
1565
|
-
// Remove dimension if field has been cleared
|
1543
|
+
// Remove dimension if field has been cleared.
|
1566
1544
|
if(dimstr.length === 0) {
|
1567
1545
|
if(!add) {
|
1568
1546
|
x.combination_dimensions.splice(this.edited_combi_dimension_index, 1);
|
1569
1547
|
}
|
1570
1548
|
} else {
|
1571
|
-
// Check for valid selector list
|
1549
|
+
// Check for valid selector list.
|
1572
1550
|
const
|
1573
1551
|
dim = dimstr.split(/\s+/g),
|
1574
1552
|
ssl = [];
|
1575
|
-
// Get this experiment's combination selector list
|
1576
|
-
for(
|
1577
|
-
|
1578
|
-
}
|
1579
|
-
// All selectors in string should have been defined
|
1553
|
+
// Get this experiment's combination selector list.
|
1554
|
+
for(const sel of x.combination_selectors) ssl.push(sel.split('|')[0]);
|
1555
|
+
// All selectors in string should have been defined.
|
1580
1556
|
let c = complement(dim, ssl);
|
1581
1557
|
if(c.length > 0) {
|
1582
1558
|
UI.warn('Combination dimension contains ' +
|
1583
1559
|
pluralS(c.length, 'unknown selector') + ': ' + c.join(' '));
|
1584
1560
|
return;
|
1585
1561
|
}
|
1586
|
-
// All selectors should expand to non-overlapping selector sets
|
1562
|
+
// All selectors should expand to non-overlapping selector sets.
|
1587
1563
|
if(!x.orthogonalCombinationDimensions(dim)) return;
|
1588
|
-
// Do not add when a (setwise) identical combination dimension exists
|
1589
|
-
for(
|
1590
|
-
const cd = x.combination_dimensions[i];
|
1564
|
+
// Do not add when a (setwise) identical combination dimension exists.
|
1565
|
+
for(const cd of x.combination_dimensions) {
|
1591
1566
|
if(intersection(dim, cd).length === dim.length) {
|
1592
1567
|
UI.notify('Combination already defined: ' + setString(cd));
|
1593
1568
|
return;
|
1594
1569
|
}
|
1595
1570
|
}
|
1596
|
-
// OK? Then add or modify
|
1571
|
+
// OK? Then add or modify.
|
1597
1572
|
if(add) {
|
1598
1573
|
x.combination_dimensions.push(dim);
|
1599
1574
|
} else {
|
@@ -1602,15 +1577,15 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1602
1577
|
}
|
1603
1578
|
}
|
1604
1579
|
this.combination_dimension_modal.hide();
|
1605
|
-
// Update combination dimensions dialog
|
1580
|
+
// Update combination dimensions dialog.
|
1606
1581
|
this.editCombinationDimensions();
|
1607
1582
|
}
|
1608
1583
|
|
1609
1584
|
editActorDimension() {
|
1610
|
-
// Open dialog for editing the actor dimension
|
1585
|
+
// Open dialog for editing the actor dimension.
|
1611
1586
|
const x = this.selected_experiment, rows = [];
|
1612
1587
|
if(x) {
|
1613
|
-
// Initialize selector list
|
1588
|
+
// Initialize selector list.
|
1614
1589
|
for(let i = 0; i < x.actor_selectors.length; i++) {
|
1615
1590
|
rows.push('<tr onclick="EXPERIMENT_MANAGER.editActorSelector(', i,
|
1616
1591
|
');"><td>', x.actor_selectors[i].selector,
|
@@ -1619,8 +1594,8 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1619
1594
|
}
|
1620
1595
|
this.actor_dimension_modal.element('table').innerHTML = rows.join('');
|
1621
1596
|
this.actor_dimension_modal.show();
|
1622
|
-
// NOTE:
|
1623
|
-
// otherwise remain visible while no longer relevant
|
1597
|
+
// NOTE: Clear infoline because dialog can generate warnings that would
|
1598
|
+
// otherwise remain visible while no longer relevant.
|
1624
1599
|
UI.setMessage('');
|
1625
1600
|
}
|
1626
1601
|
}
|
@@ -1707,17 +1682,16 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1707
1682
|
clist = [],
|
1708
1683
|
csel = md.element('select'),
|
1709
1684
|
sinp = md.element('selectors');
|
1710
|
-
// NOTE:
|
1685
|
+
// NOTE: Copy experiment property to modal dialog property, so that changes
|
1711
1686
|
// are made only when OK is clicked
|
1712
1687
|
md.clusters = [];
|
1713
|
-
for(
|
1714
|
-
|
1715
|
-
md.clusters.push({cluster: cs.cluster, selectors: cs. selectors});
|
1688
|
+
for(const cs of x.clusters_to_ignore) {
|
1689
|
+
md.clusters.push({cluster: cs.cluster, selectors: cs.selectors});
|
1716
1690
|
}
|
1717
1691
|
md.cluster_index = -1;
|
1718
1692
|
for(let k in MODEL.clusters) if(MODEL.clusters.hasOwnProperty(k)) {
|
1719
1693
|
const c = MODEL.clusters[k];
|
1720
|
-
// Do not add top cluster, nor clusters already on the list
|
1694
|
+
// Do not add top cluster, nor clusters already on the list.
|
1721
1695
|
if(c !== MODEL.top_cluster && !c.ignore && !x.mayBeIgnored(c)) {
|
1722
1696
|
clist.push(`<option value="${k}">${c.displayName}</option>`);
|
1723
1697
|
}
|
@@ -1738,7 +1712,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1738
1712
|
sdiv = md.element('selectors-div'),
|
1739
1713
|
cl = md.clusters.length;
|
1740
1714
|
if(cl > 0) {
|
1741
|
-
// Show cluster+selectors list
|
1715
|
+
// Show cluster+selectors list.
|
1742
1716
|
const ol = [];
|
1743
1717
|
for(let i = 0; i < cl; i++) {
|
1744
1718
|
const cti = md.clusters[i];
|
@@ -1751,7 +1725,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1751
1725
|
clst.style.display = 'block';
|
1752
1726
|
nlst.style.display = 'none';
|
1753
1727
|
} else {
|
1754
|
-
// Hide list and show "no clusters set to be ignored"
|
1728
|
+
// Hide list and show "no clusters set to be ignored".
|
1755
1729
|
clst.style.display = 'none';
|
1756
1730
|
nlst.style.display = 'block';
|
1757
1731
|
}
|
@@ -1767,7 +1741,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1767
1741
|
}
|
1768
1742
|
|
1769
1743
|
selectCluster(n) {
|
1770
|
-
// Set selected cluster index to `n
|
1744
|
+
// Set selected cluster index to `n`.
|
1771
1745
|
this.clusters_modal.cluster_index = n;
|
1772
1746
|
this.updateClusterList();
|
1773
1747
|
}
|
@@ -1780,7 +1754,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1780
1754
|
if(c) {
|
1781
1755
|
md.clusters.push({cluster: c, selectors: ''});
|
1782
1756
|
md.cluster_index = md.clusters.length - 1;
|
1783
|
-
// Remove cluster from select so it cannot be added again
|
1757
|
+
// Remove cluster from select so it cannot be added again.
|
1784
1758
|
sel.remove(sel.selectedIndex);
|
1785
1759
|
this.updateClusterList();
|
1786
1760
|
}
|
@@ -1803,7 +1777,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1803
1777
|
}
|
1804
1778
|
|
1805
1779
|
deleteClusterFromIgnoreList() {
|
1806
|
-
// Delete selected cluster+selectors from list
|
1780
|
+
// Delete selected cluster+selectors from list.
|
1807
1781
|
const md = this.clusters_modal;
|
1808
1782
|
if(md.cluster_index >= 0) {
|
1809
1783
|
md.clusters.splice(md.cluster_index, 1);
|
@@ -1813,7 +1787,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1813
1787
|
}
|
1814
1788
|
|
1815
1789
|
modifyClustersToIgnore() {
|
1816
|
-
// Replace current list by cluster+selectors list of modal dialog
|
1790
|
+
// Replace current list by cluster+selectors list of modal dialog.
|
1817
1791
|
const
|
1818
1792
|
md = this.clusters_modal,
|
1819
1793
|
x = this.selected_experiment;
|
@@ -1823,7 +1797,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1823
1797
|
}
|
1824
1798
|
|
1825
1799
|
promptForParameter(type) {
|
1826
|
-
// Open dialog for adding new dimension or chart
|
1800
|
+
// Open dialog for adding new dimension or chart.
|
1827
1801
|
const x = this.selected_experiment;
|
1828
1802
|
if(x) {
|
1829
1803
|
const ol = [];
|
@@ -1835,9 +1809,8 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1835
1809
|
ol.push(`<option value="${i}">${ds}</option>`);
|
1836
1810
|
}
|
1837
1811
|
} else {
|
1838
|
-
for(
|
1839
|
-
|
1840
|
-
// NOTE: exclude charts already in the selected experiment
|
1812
|
+
for(const c of this.suitable_charts) {
|
1813
|
+
// NOTE: Exclude charts already in the selected experiment.
|
1841
1814
|
if (x.charts.indexOf(c) < 0) {
|
1842
1815
|
ol.push(`<option value="${c.title}">${c.title}</option>`);
|
1843
1816
|
}
|
@@ -1849,7 +1822,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1849
1822
|
}
|
1850
1823
|
|
1851
1824
|
addParameter() {
|
1852
|
-
// Add parameter (dimension or chart) to experiment
|
1825
|
+
// Add parameter (dimension or chart) to experiment.
|
1853
1826
|
const
|
1854
1827
|
x = this.selected_experiment,
|
1855
1828
|
name = this.parameter_modal.element('select').value;
|
@@ -1871,7 +1844,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1871
1844
|
}
|
1872
1845
|
|
1873
1846
|
deleteParameter() {
|
1874
|
-
// Remove selected dimension or chart from selected experiment
|
1847
|
+
// Remove selected dimension or chart from selected experiment.
|
1875
1848
|
const
|
1876
1849
|
x = this.selected_experiment,
|
1877
1850
|
sp = this.selected_parameter;
|
@@ -1888,12 +1861,12 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1888
1861
|
}
|
1889
1862
|
|
1890
1863
|
editExclusions() {
|
1891
|
-
// Give visual feedback by setting background color to white
|
1864
|
+
// Give visual feedback by setting background color to white.
|
1892
1865
|
this.exclude.style.backgroundColor = 'white';
|
1893
1866
|
}
|
1894
1867
|
|
1895
1868
|
setExclusions() {
|
1896
|
-
// Sanitize string before accepting it as space-separated selector list
|
1869
|
+
// Sanitize string before accepting it as space-separated selector list.
|
1897
1870
|
const
|
1898
1871
|
x = this.selected_experiment;
|
1899
1872
|
if(x) {
|
@@ -1907,24 +1880,24 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1907
1880
|
}
|
1908
1881
|
|
1909
1882
|
readyButtons() {
|
1910
|
-
// Set experiment run control buttons in "ready" state
|
1883
|
+
// Set experiment run control buttons in "ready" state.
|
1911
1884
|
this.pause_btn.classList.add('off');
|
1912
1885
|
this.stop_btn.classList.add('off');
|
1913
1886
|
this.start_btn.classList.remove('off', 'blink');
|
1914
1887
|
}
|
1915
1888
|
|
1916
1889
|
pausedButtons(aci) {
|
1917
|
-
// Set experiment run control buttons in "paused" state
|
1890
|
+
// Set experiment run control buttons in "paused" state.
|
1918
1891
|
this.pause_btn.classList.remove('blink');
|
1919
1892
|
this.pause_btn.classList.add('off');
|
1920
1893
|
this.start_btn.classList.remove('off');
|
1921
|
-
// Blinking start button indicates: paused -- click to resume
|
1894
|
+
// Blinking start button indicates: paused -- click to resume.
|
1922
1895
|
this.start_btn.classList.add('blink');
|
1923
1896
|
this.viewer_progress.innerHTML = `Run ${aci} PAUSED`;
|
1924
1897
|
}
|
1925
1898
|
|
1926
1899
|
resumeButtons() {
|
1927
|
-
// Changes buttons to "running" state, and return TRUE if state was "paused"
|
1900
|
+
// Changes buttons to "running" state, and return TRUE if state was "paused".
|
1928
1901
|
const paused = this.start_btn.classList.contains('blink');
|
1929
1902
|
this.start_btn.classList.remove('blink');
|
1930
1903
|
this.start_btn.classList.add('off');
|
@@ -1934,7 +1907,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1934
1907
|
}
|
1935
1908
|
|
1936
1909
|
pauseExperiment() {
|
1937
|
-
// Interrupt solver but retain data on server and allow resume
|
1910
|
+
// Interrupt solver but retain data on server and allow resume.
|
1938
1911
|
UI.notify('Run sequence will be suspended after the current run');
|
1939
1912
|
this.pause_btn.classList.add('blink');
|
1940
1913
|
this.stop_btn.classList.remove('off');
|
@@ -1942,7 +1915,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1942
1915
|
}
|
1943
1916
|
|
1944
1917
|
stopExperiment() {
|
1945
|
-
// Interrupt solver but retain data on server (and no resume)
|
1918
|
+
// Interrupt solver but retain data on server (and no resume).
|
1946
1919
|
VM.halt();
|
1947
1920
|
MODEL.running_experiment = null;
|
1948
1921
|
UI.notify('Experiment has been stopped');
|
@@ -1951,7 +1924,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1951
1924
|
}
|
1952
1925
|
|
1953
1926
|
showProgress(ci, p, n) {
|
1954
|
-
// Show progress in the viewer
|
1927
|
+
// Show progress in the viewer.
|
1955
1928
|
this.viewer_progress.innerHTML = `Run ${ci} (${p}% of ${n})`;
|
1956
1929
|
}
|
1957
1930
|
|
@@ -1962,7 +1935,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1962
1935
|
}
|
1963
1936
|
|
1964
1937
|
promptForDownload() {
|
1965
|
-
// Show the download modal
|
1938
|
+
// Show the download modal.
|
1966
1939
|
const x = this.selected_experiment;
|
1967
1940
|
if(!x) return;
|
1968
1941
|
const
|
@@ -1975,13 +1948,13 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1975
1948
|
return;
|
1976
1949
|
}
|
1977
1950
|
md.element(ds.variables + '-v').checked = true;
|
1978
|
-
// Disable "selected runs" button when no runs have been selected
|
1951
|
+
// Disable "selected runs" button when no runs have been selected.
|
1979
1952
|
if(sruns) {
|
1980
1953
|
md.element('selected-r').disabled = false;
|
1981
1954
|
md.element(ds.runs + '-r').checked = true;
|
1982
1955
|
} else {
|
1983
1956
|
md.element('selected-r').disabled = true;
|
1984
|
-
// Check "all runs" but do not change download setting
|
1957
|
+
// Check "all runs" but do not change download setting.
|
1985
1958
|
md.element('all-r').checked = true;
|
1986
1959
|
}
|
1987
1960
|
this.download_modal.show();
|
@@ -1997,7 +1970,7 @@ N = ${rr.N}, vector length = ${rr.vector.length}` : '')].join('');
|
|
1997
1970
|
}
|
1998
1971
|
|
1999
1972
|
downloadDataAsCSV() {
|
2000
|
-
// Push results to browser
|
1973
|
+
// Push results to browser.
|
2001
1974
|
if(this.selected_experiment) {
|
2002
1975
|
const md = this.download_modal;
|
2003
1976
|
this.selected_experiment.download_settings = {
|