linny-r 1.6.7 → 1.6.8
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
CHANGED
@@ -443,6 +443,7 @@ class GUIController extends Controller {
|
|
443
443
|
// Keep track of time since last message displayed on the infoline.
|
444
444
|
this.time_last_message = new Date('01 Jan 2001 00:00:00 GMT');
|
445
445
|
this.message_display_time = 3000;
|
446
|
+
this.last_message_type = '';
|
446
447
|
|
447
448
|
// Initialize "main" modals, i.e., those that relate to the controller,
|
448
449
|
// not to other dialog objects.
|
@@ -2572,28 +2573,32 @@ class GUIController extends Controller {
|
|
2572
2573
|
// Displays message on infoline unless no type (= plain text) and some
|
2573
2574
|
// info, warning or error message is already displayed
|
2574
2575
|
super.setMessage(msg, type);
|
2576
|
+
const types = ['notification', 'warning', 'error'];
|
2575
2577
|
let d = new Date(),
|
2576
2578
|
t = d.getTime(),
|
2577
|
-
dt = t - this.time_last_message
|
2579
|
+
dt = t - this.time_last_message,
|
2580
|
+
mti = types.indexOf(type),
|
2581
|
+
lmti = types.indexOf(this.last_message_type);
|
2578
2582
|
if(type) {
|
2579
|
-
//
|
2580
|
-
this.time_last_message = t;
|
2581
|
-
dt = this.message_display_time;
|
2582
|
-
SOUNDS[type].play().catch(() => {
|
2583
|
-
console.log('NOTICE: Sounds will only play after first user action');
|
2584
|
-
});
|
2583
|
+
// Only log "real" messages.
|
2585
2584
|
const
|
2586
2585
|
now = [d.getHours(), d.getMinutes().toString().padStart(2, '0'),
|
2587
2586
|
d.getSeconds().toString().padStart(2, '0')].join(':'),
|
2588
2587
|
im = {time: now, text: msg, status: type};
|
2589
2588
|
DOCUMENTATION_MANAGER.addMessage(im);
|
2590
|
-
// When receiver is active, add message to its log
|
2589
|
+
// When receiver is active, add message to its log.
|
2591
2590
|
if(RECEIVER.active) RECEIVER.log(`[${now}] ${msg}`);
|
2592
2591
|
}
|
2593
|
-
// Display text only if previous message has "timed out" or was
|
2594
|
-
|
2592
|
+
// Display text only if previous message has "timed out" or was less
|
2593
|
+
// urgent than this one.
|
2594
|
+
if(mti > lmti || dt >= this.message_display_time) {
|
2595
|
+
this.time_last_message = t;
|
2596
|
+
this.last_message_type = type;
|
2597
|
+
if(type) SOUNDS[type].play().catch(() => {
|
2598
|
+
console.log('NOTICE: Sounds will only play after first user action');
|
2599
|
+
});
|
2595
2600
|
const il = document.getElementById('info-line');
|
2596
|
-
il.classList.remove(
|
2601
|
+
il.classList.remove(...types);
|
2597
2602
|
il.classList.add(type);
|
2598
2603
|
il.innerHTML = msg;
|
2599
2604
|
}
|
@@ -4526,6 +4526,21 @@ class VirtualMachine {
|
|
4526
4526
|
}
|
4527
4527
|
}
|
4528
4528
|
|
4529
|
+
severestIssue(list, result) {
|
4530
|
+
// Returns severest exception code or +/- INFINITY in `list`, or the
|
4531
|
+
// result of the computation that involves the elements of `list`.
|
4532
|
+
let issue = 0;
|
4533
|
+
for(let i = 0; i < list.length; i++) {
|
4534
|
+
if(list[i] <= VM.MINUS_INFINITY) {
|
4535
|
+
issue = Math.min(list[i], issue);
|
4536
|
+
} else if(list[i] >= VM.PLUS_INFINITY) {
|
4537
|
+
issue = Math.max(list[i], issue);
|
4538
|
+
}
|
4539
|
+
}
|
4540
|
+
if(issue) return issue;
|
4541
|
+
return result;
|
4542
|
+
}
|
4543
|
+
|
4529
4544
|
calculateDependentVariables(block) {
|
4530
4545
|
// Calculate the values of all model variables that depend on the
|
4531
4546
|
// values of the decision variables output by the solver.
|
@@ -4539,7 +4554,7 @@ class VirtualMachine {
|
|
4539
4554
|
cbl = this.actualBlockLength(block);
|
4540
4555
|
|
4541
4556
|
// FIRST: Calculate the actual flows on links.
|
4542
|
-
let b, bt, p, pl, ld;
|
4557
|
+
let b, bt, p, pl, ld, ci;
|
4543
4558
|
for(let l in MODEL.links) if(MODEL.links.hasOwnProperty(l) &&
|
4544
4559
|
!MODEL.ignored_entities[l]) {
|
4545
4560
|
l = MODEL.links[l];
|
@@ -4552,6 +4567,8 @@ class VirtualMachine {
|
|
4552
4567
|
// NOTE: Flows may have a delay!
|
4553
4568
|
ld = l.actualDelay(b);
|
4554
4569
|
bt = b - ld;
|
4570
|
+
// NOTE: Block index may fall beyond actual chunk length.
|
4571
|
+
ci = i - ld;
|
4555
4572
|
// NOTE: Use non-zero level here to ignore non-zero values that
|
4556
4573
|
// are very small relative to the bounds on the process
|
4557
4574
|
// (typically values below the non-zero tolerance of the solver).
|
@@ -4575,20 +4592,22 @@ class VirtualMachine {
|
|
4575
4592
|
// Similar to STARTUP, but now look in the shut-down list.
|
4576
4593
|
pl = (p.shut_downs.indexOf(bt) < 0 ? 0 : 1);
|
4577
4594
|
} else if(l.multiplier === VM.LM_INCREASE) {
|
4578
|
-
|
4595
|
+
const ppl = p.actualLevel(bt - 1);
|
4596
|
+
pl = this.severestIssue([pl, ppl], pl - ppl);
|
4579
4597
|
} else if(l.multiplier === VM.LM_SUM || l.multiplier === VM.LM_MEAN) {
|
4580
4598
|
// Level for `bt` counts as first value.
|
4581
4599
|
let count = 1;
|
4582
4600
|
// NOTE: Link delay may be < 0!
|
4583
4601
|
if(ld < 0) {
|
4584
|
-
// NOTE: Actual levels beyond
|
4602
|
+
// NOTE: Actual levels beyond the chunk length are undefined,
|
4585
4603
|
// and should be ignored while summing / averaging.
|
4586
|
-
if(
|
4604
|
+
if(ci >= cbl) pl = 0;
|
4587
4605
|
// If so, take sum over t, t+1, ..., t+(d-1).
|
4588
4606
|
for(let j = ld + 1; j <= 0; j++) {
|
4589
|
-
// Again:
|
4590
|
-
if(
|
4591
|
-
|
4607
|
+
// Again: only consider levels up to the end of the chunk.
|
4608
|
+
if(ci - j < cbl) {
|
4609
|
+
const spl = p.actualLevel(b - j);
|
4610
|
+
pl = this.severestIssue([pl, spl], pl + spl);
|
4592
4611
|
count++;
|
4593
4612
|
}
|
4594
4613
|
}
|
@@ -4597,22 +4616,24 @@ class VirtualMachine {
|
|
4597
4616
|
for(let j = 0; j < ld; j++) {
|
4598
4617
|
// NOTE: Actual levels before t=0 are considered equal to
|
4599
4618
|
// the initial level, and hence should NOT be ignored.
|
4600
|
-
|
4619
|
+
const spl = p.actualLevel(b - j);
|
4620
|
+
pl = this.severestIssue([pl, spl], pl + spl);
|
4601
4621
|
count++;
|
4602
4622
|
}
|
4603
4623
|
}
|
4604
4624
|
if(l.multiplier === VM.LM_MEAN && count > 1) {
|
4605
4625
|
// Average if more than 1 values have been summed.
|
4606
|
-
pl =
|
4626
|
+
pl = this.keepException(pl, pl / count);
|
4607
4627
|
}
|
4608
4628
|
} else if(l.multiplier === VM.LM_THROUGHPUT) {
|
4609
4629
|
// NOTE: calculate throughput on basis of levels and rates,
|
4610
4630
|
// as not all actual flows may have been computed yet
|
4611
4631
|
pl = 0;
|
4612
4632
|
for(let j = 0; j < p.inputs.length; j++) {
|
4613
|
-
|
4614
|
-
|
4615
|
-
|
4633
|
+
const
|
4634
|
+
ipl = p.inputs[j].from_node.actualLevel(bt),
|
4635
|
+
rr = p.inputs[j].relative_rate.result(bt);
|
4636
|
+
pl = this.severestIssue([pl, ipl, rr], pl + ipl * rr);
|
4616
4637
|
}
|
4617
4638
|
} else if(l.multiplier === VM.LM_PEAK_INC) {
|
4618
4639
|
// Actual flow over "peak increase" link is zero unless...
|
@@ -4627,17 +4648,10 @@ class VirtualMachine {
|
|
4627
4648
|
}
|
4628
4649
|
}
|
4629
4650
|
// Preserve special values such as INF, UNDEFINED and VM error codes.
|
4630
|
-
|
4631
|
-
|
4632
|
-
|
4633
|
-
|
4634
|
-
if(rr <= VM.MINUS_INFINITY || rr > VM.PLUS_INFINITY) {
|
4635
|
-
l.actual_flow[b] = rr;
|
4636
|
-
} else {
|
4637
|
-
const af = rr * pl;
|
4638
|
-
l.actual_flow[b] = (Math.abs(af) > VM.NEAR_ZERO ? af : 0);
|
4639
|
-
}
|
4640
|
-
}
|
4651
|
+
const
|
4652
|
+
rr = l.relative_rate.result(bt),
|
4653
|
+
af = this.severestIssue([pl, rr], rr * pl);
|
4654
|
+
l.actual_flow[b] = (Math.abs(af) > VM.NEAR_ZERO ? af : 0);
|
4641
4655
|
b++;
|
4642
4656
|
}
|
4643
4657
|
}
|
@@ -5586,24 +5600,33 @@ Solver status = ${json.status}`);
|
|
5586
5600
|
// levels and stock level), but do NOT overwrite "look-ahead" levels
|
5587
5601
|
// if this block was not solved (indicated by the 4th parameter that
|
5588
5602
|
// tests the status).
|
5589
|
-
|
5590
|
-
|
5591
|
-
|
5592
|
-
|
5593
|
-
|
5594
|
-
|
5595
|
-
|
5596
|
-
|
5597
|
-
|
5598
|
-
|
5599
|
-
|
5600
|
-
|
5601
|
-
|
5602
|
-
|
5603
|
-
|
5604
|
-
|
5605
|
-
|
5606
|
-
|
5603
|
+
try {
|
5604
|
+
this.setLevels(bnr, rl, json.data.x,
|
5605
|
+
// NOTE: Appropriate status codes are solver-dependent.
|
5606
|
+
this.noSolutionStatus.indexOf(json.status) >= 0);
|
5607
|
+
// NOTE: Post-process levels only AFTER the last round!
|
5608
|
+
if(rl === this.lastRound) {
|
5609
|
+
// Calculate data for all other dependent variables.
|
5610
|
+
this.calculateDependentVariables(bnr);
|
5611
|
+
// Add progress bar segment only now, knowing status AND slack use.
|
5612
|
+
const issue = json.status !== 0 || this.error_count > 0;
|
5613
|
+
if(issue) this.block_issues++;
|
5614
|
+
// NOTE: in case of multiple rounds, use the sum of the round times.
|
5615
|
+
const time = this.round_times.reduce((a, b) => a + b, 0);
|
5616
|
+
this.round_times.length = 0;
|
5617
|
+
this.solver_times[bnr - 1] = time;
|
5618
|
+
const ssecs = this.round_secs.reduce((a, b) => a + b, 0);
|
5619
|
+
this.solver_secs[bnr - 1] = (ssecs ? VM.sig4Dig(ssecs) : '0');
|
5620
|
+
this.round_secs.length = 0;
|
5621
|
+
MONITOR.addProgressBlock(bnr, issue, time);
|
5622
|
+
}
|
5623
|
+
} catch(err) {
|
5624
|
+
const msg = `ERROR while processing solver data for block ${bnr}: ${err}`;
|
5625
|
+
console.log(msg);
|
5626
|
+
MONITOR.logMessage(bnr, msg);
|
5627
|
+
UI.alert(msg);
|
5628
|
+
this.stopSolving();
|
5629
|
+
this.halted = true;
|
5607
5630
|
}
|
5608
5631
|
// Free up memory.
|
5609
5632
|
json = null;
|