linny-r 1.7.0 → 1.7.2
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/console.js +150 -89
- package/package.json +1 -1
- package/server.js +1 -1
- package/static/scripts/linny-r-ctrl.js +16 -13
- package/static/scripts/linny-r-gui-paper.js +43 -38
- package/static/scripts/linny-r-gui-receiver.js +5 -5
- package/static/scripts/linny-r-model.js +188 -155
- package/static/scripts/linny-r-utils.js +20 -3
- package/static/scripts/linny-r-vm.js +581 -327
@@ -1584,10 +1584,10 @@ class Paper {
|
|
1584
1584
|
if(luc && MODEL.infer_cost_prices &&
|
1585
1585
|
af > VM.MINUS_INFINITY && af < VM.PLUS_INFINITY
|
1586
1586
|
) {
|
1587
|
-
// Assume no cost price to be displayed
|
1587
|
+
// Assume no cost price to be displayed.
|
1588
1588
|
s = '';
|
1589
1589
|
let soc = 0;
|
1590
|
-
// NOTE:
|
1590
|
+
// NOTE: Flows INTO processes always carry cost.
|
1591
1591
|
if(luc.to_node instanceof Process) {
|
1592
1592
|
soc = 1;
|
1593
1593
|
prod = luc.from_node;
|
@@ -1607,7 +1607,7 @@ class Paper {
|
|
1607
1607
|
// ... unless it is a flow of a by-product having a market
|
1608
1608
|
// value (+ or -)
|
1609
1609
|
if(cp !== 0) {
|
1610
|
-
//Just in case, check for error codes (if so, display them)
|
1610
|
+
// Just in case, check for error codes (if so, display them).
|
1611
1611
|
if(cp < VM.MINUS_INFINITY) {
|
1612
1612
|
s = VM.sig4Dig(cp);
|
1613
1613
|
} else if(cp < 0) {
|
@@ -1616,53 +1616,57 @@ class Paper {
|
|
1616
1616
|
}
|
1617
1617
|
}
|
1618
1618
|
} else {
|
1619
|
+
const d = luc.actualDelay(MODEL.t);
|
1619
1620
|
if(af > 0) {
|
1620
|
-
// Positive flow => use cost price of FROM node
|
1621
|
+
// Positive flow => use cost price of FROM node.
|
1621
1622
|
if(luc.from_node instanceof Process) {
|
1622
1623
|
// For processes, this is their cost price per level
|
1623
|
-
// DIVIDED BY the relative rate of the link
|
1624
|
+
// DIVIDED BY the relative rate of the link.
|
1624
1625
|
const rr = luc.relative_rate.result(MODEL.t);
|
1625
1626
|
if(Math.abs(rr) < VM.NEAR_ZERO) {
|
1626
1627
|
cp = (rr < 0 && cp < 0 || rr > 0 && cp > 0 ?
|
1627
1628
|
VM.PLUS_INFINITY : VM.MINUS_INFINITY);
|
1628
1629
|
} else {
|
1629
|
-
cp = proc.costPrice(MODEL.t) / rr;
|
1630
|
+
cp = proc.costPrice(MODEL.t - d) / rr;
|
1630
1631
|
}
|
1631
1632
|
} else if(prod.price.defined) {
|
1632
1633
|
// For products their market price if defined...
|
1633
|
-
cp = prod.price.result(MODEL.t);
|
1634
|
+
cp = prod.price.result(MODEL.t - d);
|
1634
1635
|
} else {
|
1635
|
-
// ... otherwise their cost price
|
1636
|
-
cp = prod.costPrice(MODEL.t);
|
1636
|
+
// ... otherwise their cost price.
|
1637
|
+
cp = prod.costPrice(MODEL.t - d);
|
1637
1638
|
}
|
1638
1639
|
} else {
|
1639
|
-
// Negative flow => use cost price of TO node
|
1640
|
+
// Negative flow => use cost price of TO node.
|
1640
1641
|
if(luc.to_node instanceof Process) {
|
1642
|
+
// NOTE: Input links have no delay.
|
1641
1643
|
cp = proc.costPrice(MODEL.t);
|
1642
1644
|
} else if(prod.price.defined) {
|
1643
|
-
cp = prod.price.result(MODEL.t);
|
1645
|
+
cp = prod.price.result(MODEL.t - d);
|
1644
1646
|
} else {
|
1645
|
-
cp = prod.costPrice(MODEL.t);
|
1647
|
+
cp = prod.costPrice(MODEL.t - d);
|
1646
1648
|
}
|
1647
1649
|
}
|
1648
|
-
// NOTE:
|
1650
|
+
// NOTE: The first condition ensures that error codes will be
|
1651
|
+
// displayed.
|
1649
1652
|
if(cp <= VM.MINUS_INFINITY || cp >= VM.PLUS_INFINITY) {
|
1650
1653
|
s = VM.sig4Dig(cp);
|
1651
1654
|
} else if(Math.abs(cp) <= VM.SIG_DIF_FROM_ZERO) {
|
1652
|
-
// DO not display CP when it is "propagated" NO_COST
|
1655
|
+
// DO not display CP when it is "propagated" NO_COST.
|
1653
1656
|
s = (cp === VM.NO_COST ? '' : '0');
|
1654
1657
|
} else {
|
1655
|
-
// NOTE:
|
1658
|
+
// NOTE: Use the absolute value of the flow, as cost is not
|
1659
|
+
// affected by direction.
|
1656
1660
|
s = VM.sig4Dig(Math.abs(af) * soc * cp);
|
1657
1661
|
}
|
1658
1662
|
}
|
1659
|
-
// Only display cost price if it is meaningful
|
1663
|
+
// Only display cost price if it is meaningful.
|
1660
1664
|
if(s) {
|
1661
1665
|
font_color = 'gray';
|
1662
1666
|
bb = this.numberSize(s, 8, font_weight);
|
1663
1667
|
tw = bb.width;
|
1664
1668
|
th = bb.height;
|
1665
|
-
// NOTE:
|
1669
|
+
// NOTE: Offset cost price label relative to actual flow label.
|
1666
1670
|
epy += th + 1;
|
1667
1671
|
arrw.shape.addRect(epx, epy, tw, th, {'fill': this.palette.cost_price});
|
1668
1672
|
arrw.shape.addNumber(epx, epy, s, {'fill': font_color});
|
@@ -1671,15 +1675,16 @@ class Paper {
|
|
1671
1675
|
} // end IF l > 0 and actual flow is defined and non-zero
|
1672
1676
|
|
1673
1677
|
if(l > 0) {
|
1674
|
-
// NOTE:
|
1675
|
-
// product that has the "hide links" option selected
|
1678
|
+
// NOTE: Make the arrow shape nearly transparant when it connects
|
1679
|
+
// to a product that has the "hide links" option selected.
|
1676
1680
|
if(arrw.from_node.no_links || arrw.to_node.no_links) {
|
1677
1681
|
arrw.shape.element.setAttribute('opacity', 0.08);
|
1678
1682
|
}
|
1679
1683
|
arrw.shape.appendToDOM();
|
1680
1684
|
return true;
|
1681
1685
|
}
|
1682
|
-
// If nothing is drawn, return FALSE although this does NOT imply an
|
1686
|
+
// If nothing is drawn, return FALSE although this does NOT imply an
|
1687
|
+
// error.
|
1683
1688
|
return false;
|
1684
1689
|
}
|
1685
1690
|
|
@@ -2107,16 +2112,16 @@ class Paper {
|
|
2107
2112
|
const ubs = (ub >= VM.PLUS_INFINITY && !proc.upper_bound.defined ?
|
2108
2113
|
'\u221E' : VM.sig4Dig(ub));
|
2109
2114
|
if(Math.abs(lb) > VM.NEAR_ZERO) {
|
2110
|
-
// If lb <> 0 then lb...ub (with ellipsis)
|
2115
|
+
// If lb <> 0 then lb...ub (with ellipsis).
|
2111
2116
|
s += '\u2026' + ubs;
|
2112
2117
|
} else {
|
2113
|
-
// If lb = 0 show only the upper bound
|
2118
|
+
// If lb = 0 show only the upper bound.
|
2114
2119
|
s = ubs;
|
2115
2120
|
lbw = 0;
|
2116
2121
|
}
|
2117
2122
|
}
|
2118
2123
|
// Keep track of the width of the boundary text, as later it may be
|
2119
|
-
// followed by more text
|
2124
|
+
// followed by more text.
|
2120
2125
|
const
|
2121
2126
|
bb = this.numberSize(s),
|
2122
2127
|
btw = bb.width + 2,
|
@@ -2125,18 +2130,18 @@ class Paper {
|
|
2125
2130
|
ty = y - hh + sh/2 + 1;
|
2126
2131
|
proc.shape.addNumber(tx + btw/2, ty, s,
|
2127
2132
|
{fill: 'black', 'font-style': bfs});
|
2128
|
-
// Show start/stop-related status right of the process boundaries
|
2129
|
-
// NOTE: lb must be > 0 for start/stop to work
|
2133
|
+
// Show start/stop-related status right of the process boundaries.
|
2134
|
+
// NOTE: lb must be > 0 for start/stop to work.
|
2130
2135
|
if(proc.level_to_zero && lbw) {
|
2131
2136
|
font_color = 'black';
|
2132
|
-
// Underline the lower bound to indicate semi-continuity
|
2137
|
+
// Underline the lower bound to indicate semi-continuity.
|
2133
2138
|
proc.shape.addPath(
|
2134
2139
|
['M', tx + lbo, ',', ty + sh/2, 'L', tx + lbo + lbw, ',', ty + sh/2],
|
2135
2140
|
{'fill': 'none', stroke: font_color, 'stroke-width': 0.4});
|
2136
|
-
// By default, no ON/OFF indicator
|
2141
|
+
// By default, no ON/OFF indicator.
|
2137
2142
|
s = '';
|
2138
2143
|
if(MODEL.solved && l !== VM.UNDEFINED) {
|
2139
|
-
// Solver has been active
|
2144
|
+
// Solver has been active.
|
2140
2145
|
const
|
2141
2146
|
pl = proc.actualLevel(MODEL.t - 1),
|
2142
2147
|
su = proc.start_ups.indexOf(MODEL.t),
|
@@ -2145,36 +2150,36 @@ class Paper {
|
|
2145
2150
|
// Process is ON
|
2146
2151
|
if(Math.abs(pl) < VM.NEAR_ZERO && su >= 0) {
|
2147
2152
|
font_color = this.palette.switch_on_off;
|
2148
|
-
// Start-up arrow or first-commit asterisk
|
2153
|
+
// Start-up arrow or first-commit asterisk.
|
2149
2154
|
s = VM.LM_SYMBOLS[su ? VM.LM_STARTUP : VM.LM_FIRST_COMMIT];
|
2150
2155
|
} else if(su >= 0) {
|
2151
2156
|
font_color = 'black';
|
2152
|
-
s = '\u25B3'; // Outline triangle up to indicate anomaly
|
2157
|
+
s = '\u25B3'; // Outline triangle up to indicate anomaly.
|
2153
2158
|
}
|
2154
2159
|
if(sd >= 0) {
|
2155
|
-
// Should not occur, as for shut-down, level should be 0
|
2160
|
+
// Should not occur, as for shut-down, level should be 0.
|
2156
2161
|
font_color = 'black';
|
2157
|
-
s += '\u25BD'; // Add outline triangle down to indicate anomaly
|
2162
|
+
s += '\u25BD'; // Add outline triangle down to indicate anomaly.
|
2158
2163
|
}
|
2159
2164
|
} else {
|
2160
|
-
// Process is OFF => check previous level
|
2165
|
+
// Process is OFF => check previous level.
|
2161
2166
|
if(Math.abs(pl) > VM.NEAR_ZERO && sd >= 0) {
|
2162
|
-
// Process was on, and is now switched OFF
|
2167
|
+
// Process was on, and is now switched OFF.
|
2163
2168
|
font_color = this.palette.switch_on_off;
|
2164
2169
|
s = VM.LM_SYMBOLS[VM.LM_SHUTDOWN];
|
2165
2170
|
} else if(sd >= 0) {
|
2166
2171
|
font_color = 'black';
|
2167
|
-
s = '\u25BD'; // Outline triangle down to indicate anomaly
|
2172
|
+
s = '\u25BD'; // Outline triangle down to indicate anomaly.
|
2168
2173
|
}
|
2169
2174
|
if(su >= 0) {
|
2170
|
-
// Should not occur, as for start-up, level should be > 0
|
2175
|
+
// Should not occur, as for start-up, level should be > 0.
|
2171
2176
|
font_color = 'black';
|
2172
|
-
s += '\u25B3'; // Add outline triangle up to indicate anomaly
|
2177
|
+
s += '\u25B3'; // Add outline triangle up to indicate anomaly.
|
2173
2178
|
}
|
2174
2179
|
}
|
2175
2180
|
}
|
2176
2181
|
if(s) {
|
2177
|
-
// Special symbols are 5 pixels wide and 9 high
|
2182
|
+
// Special symbols are 5 pixels wide and 9 high.
|
2178
2183
|
proc.shape.addText(x - hw + btw + 5, y - hh + 4.5, s,
|
2179
2184
|
{fill: font_color});
|
2180
2185
|
}
|
@@ -199,7 +199,7 @@ class GUIReceiver {
|
|
199
199
|
// Keep listening, so check again after the time interval
|
200
200
|
setTimeout(() => RECEIVER.listen(), RECEIVER.interval);
|
201
201
|
})
|
202
|
-
.catch(() => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
202
|
+
.catch((err) => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
203
203
|
} else {
|
204
204
|
RECEIVER.log('Executing: ' + RECEIVER.file_name);
|
205
205
|
// NOTE: Virtual Machine will trigger the receiver's reporting
|
@@ -216,7 +216,7 @@ class GUIReceiver {
|
|
216
216
|
}
|
217
217
|
}
|
218
218
|
})
|
219
|
-
.catch(() => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
219
|
+
.catch((err) => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
220
220
|
}
|
221
221
|
|
222
222
|
report() {
|
@@ -232,7 +232,7 @@ class GUIReceiver {
|
|
232
232
|
if(this.experiment || !this.active) {
|
233
233
|
if(MODEL.running_experiment) {
|
234
234
|
run = MODEL.running_experiment.active_combination_index;
|
235
|
-
this.log(`Reporting: ${
|
235
|
+
this.log(`Reporting: ${file} (run #${run})`);
|
236
236
|
}
|
237
237
|
}
|
238
238
|
// NOTE: If receiver is not active, path and file must be set.
|
@@ -284,7 +284,7 @@ class GUIReceiver {
|
|
284
284
|
// the Experiment Manager.
|
285
285
|
if(RECEIVER.active && !RECEIVER.experiment) RECEIVER.callBack();
|
286
286
|
})
|
287
|
-
.catch(() => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
287
|
+
.catch((err) => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
288
288
|
}
|
289
289
|
|
290
290
|
callBack() {
|
@@ -317,7 +317,7 @@ class GUIReceiver {
|
|
317
317
|
}
|
318
318
|
}
|
319
319
|
})
|
320
|
-
.catch(() => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
320
|
+
.catch((err) => UI.warn(UI.WARNING.NO_CONNECTION, err));
|
321
321
|
}
|
322
322
|
|
323
323
|
} // END of class GUIReceiver
|