linny-r 2.0.11 → 2.0.12
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 +1 -1
- package/static/scripts/linny-r-ctrl.js +18 -13
- package/static/scripts/linny-r-gui-controller.js +11 -9
- package/static/scripts/linny-r-gui-dataset-manager.js +3 -1
- package/static/scripts/linny-r-gui-experiment-manager.js +3 -3
- package/static/scripts/linny-r-gui-finder.js +10 -1
- package/static/scripts/linny-r-vm.js +23 -2
package/package.json
CHANGED
@@ -1266,30 +1266,30 @@ class ExperimentManager {
|
|
1266
1266
|
}
|
1267
1267
|
|
1268
1268
|
startExperiment(n=-1) {
|
1269
|
-
// Recompile expressions, as these may have been changed by the modeler
|
1269
|
+
// Recompile expressions, as these may have been changed by the modeler.
|
1270
1270
|
MODEL.compileExpressions();
|
1271
|
-
// Start sequence of solving model parametrizations
|
1271
|
+
// Start sequence of solving model parametrizations.
|
1272
1272
|
const x = this.selected_experiment;
|
1273
1273
|
if(x) {
|
1274
|
-
// Store original model settings
|
1274
|
+
// Store original model settings.
|
1275
1275
|
x.original_model_settings = MODEL.settingsString;
|
1276
1276
|
x.original_round_sequence = MODEL.round_sequence;
|
1277
|
-
// NOTE:
|
1277
|
+
// NOTE: Switch off run chart display.
|
1278
1278
|
CHART_MANAGER.setRunsChart(false);
|
1279
1279
|
// When Chart manager is showing, close it and notify modeler that charts
|
1280
|
-
// should not be viewed during experiments
|
1280
|
+
// should not be viewed during experiments.
|
1281
1281
|
if(CHART_MANAGER.visible) {
|
1282
1282
|
UI.buttons.chart.dispatchEvent(new Event('click'));
|
1283
1283
|
UI.notify(UI.NOTICE.NO_CHARTS);
|
1284
1284
|
}
|
1285
|
-
// Change the buttons -- will return TRUE if experiment was paused
|
1285
|
+
// Change the buttons -- will return TRUE if experiment was paused.
|
1286
1286
|
const paused = this.resumeButtons();
|
1287
1287
|
if(x.completed && n >= 0) {
|
1288
1288
|
x.single_run = n;
|
1289
1289
|
x.active_combination_index = n;
|
1290
1290
|
MODEL.running_experiment = x;
|
1291
1291
|
} else if(!paused) {
|
1292
|
-
// Clear previous run results (if any) unless resuming
|
1292
|
+
// Clear previous run results (if any) unless resuming.
|
1293
1293
|
x.clearRuns();
|
1294
1294
|
x.inferVariables();
|
1295
1295
|
x.time_started = new Date().getTime();
|
@@ -1369,11 +1369,14 @@ class ExperimentManager {
|
|
1369
1369
|
// Perform post-processing after run results have been added.
|
1370
1370
|
const x = MODEL.running_experiment;
|
1371
1371
|
if(!x) return;
|
1372
|
-
const
|
1372
|
+
const
|
1373
|
+
aci = x.active_combination_index,
|
1374
|
+
single = (aci == x.single_run);
|
1373
1375
|
// Always add solver messages.
|
1374
1376
|
x.runs[aci].addMessages();
|
1375
1377
|
const n = x.combinations.length;
|
1376
|
-
if(!VM.halted && aci < n - 1 &&
|
1378
|
+
if(!VM.halted && aci < n - 1 && !single) {
|
1379
|
+
// Continue with the next run.
|
1377
1380
|
if(this.must_pause) {
|
1378
1381
|
this.pausedButtons(aci);
|
1379
1382
|
this.must_pause = false;
|
@@ -1384,12 +1387,13 @@ class ExperimentManager {
|
|
1384
1387
|
// NOTE: When executing a remote command, wait for 1 second to
|
1385
1388
|
// allow enough time for report writing.
|
1386
1389
|
if(RECEIVER.active && RECEIVER.experiment) {
|
1387
|
-
UI.setMessage('Reporting run #' +
|
1390
|
+
UI.setMessage('Reporting run #' + aci);
|
1388
1391
|
delay = 1000;
|
1389
1392
|
}
|
1390
1393
|
setTimeout(() => EXPERIMENT_MANAGER.runModel(), delay);
|
1391
1394
|
}
|
1392
1395
|
} else {
|
1396
|
+
// Stop the run sequence.
|
1393
1397
|
x.time_stopped = new Date().getTime();
|
1394
1398
|
if(x.single_run >= 0) {
|
1395
1399
|
x.single_run = -1;
|
@@ -1409,18 +1413,19 @@ class ExperimentManager {
|
|
1409
1413
|
RECEIVER.experiment = '';
|
1410
1414
|
RECEIVER.callBack();
|
1411
1415
|
}
|
1412
|
-
// Restore original model settings
|
1416
|
+
// Restore original model settings.
|
1413
1417
|
MODEL.running_experiment = null;
|
1414
1418
|
MODEL.parseSettings(x.original_model_settings);
|
1415
1419
|
MODEL.round_sequence = x.original_round_sequence;
|
1416
1420
|
// Reset the Virtual Machine so t=0 at the status line,
|
1417
1421
|
// and ALL expressions are reset as well.
|
1418
|
-
VM.reset();
|
1422
|
+
if(!single) VM.reset();
|
1419
1423
|
this.readyButtons();
|
1420
1424
|
}
|
1421
1425
|
this.drawTable();
|
1422
1426
|
// Reset the model, as results of last run will be showing still.
|
1423
|
-
|
1427
|
+
// NOTE: Do NOT do this after a single run.
|
1428
|
+
if(!single) UI.resetModel();
|
1424
1429
|
CHART_MANAGER.resetChartVectors();
|
1425
1430
|
// NOTE: Clear chart only when done; charts do not update when an
|
1426
1431
|
// experiment is running.
|
@@ -1710,14 +1710,14 @@ class GUIController extends Controller {
|
|
1710
1710
|
//
|
1711
1711
|
|
1712
1712
|
draggableDialog(d) {
|
1713
|
-
// Make dialog draggable
|
1713
|
+
// Make dialog draggable.
|
1714
1714
|
const
|
1715
1715
|
dlg = document.getElementById(d + '-dlg'),
|
1716
1716
|
hdr = document.getElementById(d + '-hdr');
|
1717
1717
|
let cx = 0,
|
1718
1718
|
cy = 0;
|
1719
1719
|
if(dlg && hdr) {
|
1720
|
-
// NOTE:
|
1720
|
+
// NOTE: Dialogs are draggable only by their header.
|
1721
1721
|
hdr.onmousedown = dialogHeaderMouseDown;
|
1722
1722
|
dlg.onmousedown = dialogMouseDown;
|
1723
1723
|
return dlg;
|
@@ -1728,13 +1728,13 @@ class GUIController extends Controller {
|
|
1728
1728
|
|
1729
1729
|
function dialogMouseDown(e) {
|
1730
1730
|
e = e || window.event;
|
1731
|
-
// NOTE:
|
1732
|
-
// Find the dialog element
|
1731
|
+
// NOTE: No `preventDefault`, as this disables selector elements.
|
1732
|
+
// Find the dialog element.
|
1733
1733
|
let de = e.target;
|
1734
1734
|
while(de && !de.id.endsWith('-dlg')) { de = de.parentElement; }
|
1735
|
-
//
|
1735
|
+
// Move the dialog (`this`) to the top of the order.
|
1736
1736
|
const doi = UI.dr_dialog_order.indexOf(de);
|
1737
|
-
// NOTE:
|
1737
|
+
// NOTE: Do not reorder when already at end of list (= at top).
|
1738
1738
|
if(doi >= 0 && doi !== UI.dr_dialog_order.length - 1) {
|
1739
1739
|
UI.dr_dialog_order.splice(doi, 1);
|
1740
1740
|
UI.dr_dialog_order.push(de);
|
@@ -1745,12 +1745,12 @@ class GUIController extends Controller {
|
|
1745
1745
|
function dialogHeaderMouseDown(e) {
|
1746
1746
|
e = e || window.event;
|
1747
1747
|
e.preventDefault();
|
1748
|
-
// Find the dialog element
|
1748
|
+
// Find the dialog element.
|
1749
1749
|
let de = e.target;
|
1750
1750
|
while(de && !de.id.endsWith('-dlg')) { de = de.parentElement; }
|
1751
|
-
// Record the affected dialog
|
1751
|
+
// Record the affected dialog.
|
1752
1752
|
UI.dr_dialog = de;
|
1753
|
-
// Get the mouse cursor position at startup
|
1753
|
+
// Get the mouse cursor position at startup.
|
1754
1754
|
cx = e.clientX;
|
1755
1755
|
cy = e.clientY;
|
1756
1756
|
document.onmouseup = stopDragDialog;
|
@@ -2258,6 +2258,8 @@ class GUIController extends Controller {
|
|
2258
2258
|
this.net_move_y = 0;
|
2259
2259
|
// Get the paper coordinates indicated by the cursor.
|
2260
2260
|
const cp = this.paper.cursorPosition(e.pageX, e.pageY);
|
2261
|
+
this.mouse_x = cp[0];
|
2262
|
+
this.mouse_y = cp[1];
|
2261
2263
|
this.mouse_down_x = cp[0];
|
2262
2264
|
this.mouse_down_y = cp[1];
|
2263
2265
|
// De-activate "stay active" buttons if dysfunctional, or if SHIFT,
|
@@ -1261,7 +1261,7 @@ class GUIDatasetManager extends DatasetManager {
|
|
1261
1261
|
ods = MODEL.namedObjectByID(id),
|
1262
1262
|
ds = ods || MODEL.addDataset(n);
|
1263
1263
|
// NOTE: `ds` will now be either a new dataset or an existing one.
|
1264
|
-
if(ds) {
|
1264
|
+
if(ds instanceof Dataset) {
|
1265
1265
|
// Keep track of added/updated datasets.
|
1266
1266
|
const
|
1267
1267
|
odv = ds.default_value,
|
@@ -1274,6 +1274,8 @@ class GUIDatasetManager extends DatasetManager {
|
|
1274
1274
|
added++;
|
1275
1275
|
}
|
1276
1276
|
ds.computeStatistics();
|
1277
|
+
} else {
|
1278
|
+
UI.warn(`Name conflict: ${ds.type} "${ds.displayName}" already exists`);
|
1277
1279
|
}
|
1278
1280
|
}
|
1279
1281
|
// Notify modeler of changes (if any).
|
@@ -844,8 +844,8 @@ class GUIExperimentManager extends ExperimentManager {
|
|
844
844
|
}
|
845
845
|
|
846
846
|
showInfo(n, shift) {
|
847
|
-
// Display documentation for the n-th experiment defined in the model
|
848
|
-
// NOTE:
|
847
|
+
// Display documentation for the n-th experiment defined in the model.
|
848
|
+
// NOTE: Skip when viewer is showing!
|
849
849
|
if(!UI.hidden('experiment-viewer')) return;
|
850
850
|
if(n < MODEL.experiments.length) {
|
851
851
|
// NOTE: mouse move over title in viewer passes n = -1
|
@@ -856,7 +856,7 @@ class GUIExperimentManager extends ExperimentManager {
|
|
856
856
|
|
857
857
|
showRunInfo(n, shift) {
|
858
858
|
// Display information on the n-th combination if docu-viewer is visible
|
859
|
-
// and cursor is moved over run cell while Shift button is held down
|
859
|
+
// and cursor is moved over run cell while Shift button is held down.
|
860
860
|
if(shift && DOCUMENTATION_MANAGER.visible) {
|
861
861
|
const info = this.runInfo(n);
|
862
862
|
if(info) {
|
@@ -949,7 +949,16 @@ class Finder {
|
|
949
949
|
}
|
950
950
|
}
|
951
951
|
// Set the new default selector (if changed).
|
952
|
-
if(md.new_defsel !== false)
|
952
|
+
if(md.new_defsel !== false) {
|
953
|
+
// NOTE: `new_defsel` is a key; the actual selector name may have upper case
|
954
|
+
// letters, so get the selector name.
|
955
|
+
const dsm = ds.modifiers[md.new_defsel];
|
956
|
+
if(dsm) {
|
957
|
+
ds.default_selector = dsm.selector;
|
958
|
+
} else {
|
959
|
+
throw(`Unknown selector: ${md.new_defsel}`);
|
960
|
+
}
|
961
|
+
}
|
953
962
|
}
|
954
963
|
// Notify modeler of changes (if any).
|
955
964
|
const msg = [];
|
@@ -7204,7 +7204,13 @@ function VMI_push_run_result(x, args) {
|
|
7204
7204
|
let xp = rrspec.x,
|
7205
7205
|
rn = rrspec.r,
|
7206
7206
|
rri = rrspec.v;
|
7207
|
-
if(xp === false)
|
7207
|
+
if(xp === false) {
|
7208
|
+
// If no experiment is specified, use the running experiment.
|
7209
|
+
// NOTE: To facilitate testing a "single run" without using the
|
7210
|
+
// Experiment manager, default to the experiment that is selected
|
7211
|
+
// in the Experiment manager (but not "running").
|
7212
|
+
xp = MODEL.running_experiment || EXPERIMENT_MANAGER.selected_experiment;
|
7213
|
+
}
|
7208
7214
|
if(xp instanceof Experiment) {
|
7209
7215
|
if(Array.isArray(rn)) {
|
7210
7216
|
// Let the running experiment infer run number from selector list `rn`
|
@@ -7212,7 +7218,22 @@ function VMI_push_run_result(x, args) {
|
|
7212
7218
|
rn = xp.matchingCombinationIndex(rn);
|
7213
7219
|
} else if(rn < 0) {
|
7214
7220
|
// Relative run number: use current run # + r (first run has number 0).
|
7215
|
-
|
7221
|
+
if(xp === MODEL.running_experiment) {
|
7222
|
+
rn += xp.active_combination_index;
|
7223
|
+
} else if(xp.chart_combinations.length) {
|
7224
|
+
// Modeler has selected one or more runs in the viewer table.
|
7225
|
+
// FInd the highest number of a selected run that has been performed.
|
7226
|
+
let last = -1;
|
7227
|
+
for(const ccn of xp.chart_combinations) {
|
7228
|
+
if(ccn > last && ccn < xp.runs.length) last = ccn;
|
7229
|
+
}
|
7230
|
+
// If no performed runs are selected, use the last performed run.
|
7231
|
+
if(last < 0) last = xp.runs.length - 1;
|
7232
|
+
rn += last;
|
7233
|
+
} else {
|
7234
|
+
// Choose the run relative to the total number of completed runs.
|
7235
|
+
rn += xp.runs.length - 1;
|
7236
|
+
}
|
7216
7237
|
} else if(rrspec.nr !== false) {
|
7217
7238
|
// Run number inferred from local time step of expression.
|
7218
7239
|
const
|