Last active
December 3, 2024 18:19
-
-
Save kenwebb/105e5059b60bde86f5ddc6f1b5e44def to your computer and use it in GitHub Desktop.
Industrial Dynamics - Chapter 15 - Xholonish - Distributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Tue Dec 03 2024 13:18:29 GMT-0500 (Eastern Standard Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Industrial Dynamics - Chapter 15 - Xholonish - Distributor | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 105e5059b60bde86f5ddc6f1b5e44def based on 82a5616d810776f53ed5e0b79c2d3e74, c8c90e6e6d761e1268747bb1b5e0d430 | |
Keywords: | |
My Notes | |
-------- | |
22 Nov 2024 | |
The second of three workbooks: Retail, Distributor, Factory | |
- connect the three at runtime using broadcastChannel | |
- use arrow functions within beh to implement DYNAMO auxiliaries | |
α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ σ τ υ φ χ ψ ω | |
This Distributor version generates exactly the same values as the Retail workbook. | |
### TODO | |
- connect the Retail and Distributor workbooks; see Figure 15-14 and Figure 15-15 in the Forrester book | |
- I have done this using broadcastChannel | |
### References | |
() Jay Forrester, Industrial Dynamics, 1961 | |
() https://developer.mozilla.org/en-US/blog/exploring-the-broadcast-channel-api-for-cross-tab-communication/ | |
]]></Notes> | |
<_-.XholonClass> | |
<DynamicalSystem> | |
<!-- Production - Distribution System, chapters 2, 15 --> | |
<ProdDistSystem/> | |
</DynamicalSystem> | |
<Distributor/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
<Avatar><Color>red</Color></Avatar> | |
</xholonClassDetails> | |
<ProdDistSystem> | |
<Distributor/> | |
</ProdDistSystem> | |
<Distributorbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
// what is special about these? why are they here? | |
// TODO convert to Distributor, if needed | |
//const RRR = {KL:1}; // Requisitions (orders) Received at Retail (units/week) from customers | |
//const RCR = {K:1}; // ??? | |
//const STP = {K:1}; | |
//const SNE = {K:1}; | |
//const STR = {K:1}; // already done below | |
//const TIME = {K:1}; | |
// what is special about these? why are they here? | |
// TODO convert to Distributor, if needed | |
const | |
//PER=1, | |
//RRI=1, | |
//SIH=1, | |
STH=1, | |
STT=1; | |
// constants | |
const | |
AID = 8, | |
DCD = 3, | |
DHD = 1, | |
DID = 4, | |
DMD = 0.5, | |
DRD = 8, | |
DTD = 1, | |
DUD = 0.4; | |
const DT = 1; // Delta Time (weeks), the time interval between solutions of the equations | |
// DISTRIBUTOR ------------------------ | |
// levels | |
const CPD={K:1.1}; | |
const IAD={K:1.2}; | |
const MTD={K:1.3}; | |
const PMD={K:1.4}; | |
const RSD={K:1.5}; | |
const UOD={K:1.6}; // Unfilled Orders at Distributor (measured in units of goods on order) | |
// rates | |
const PDD={KL:1}; | |
const PSD={KL:1}; | |
const RRF={KL:1}; // to factory | |
const SRD={KL:1}; | |
const SSD={KL:1}; // Shipments Sent from Retail (units/week) | |
// auxiliary | |
// these are recalculated from scratch each time step | |
const DFD={K:1}; | |
const IDD={K:1}; | |
const LAD={K:1}; | |
const LDD={K:1}; | |
//const MND={K:1}; | |
const NID={K:1}; | |
const STD={K:1}; | |
const UND={K:1}; | |
// from retail | |
const RRD = {KL:1}; | |
// from factory | |
const DFF = {J: 4, K:4}; | |
const UOF = {J: 1, K:1}; | |
const SSF = {JK: 1,KL:1}; | |
//functions, lambdas TODO done | |
// LDR.K=(RSR.K)*(DCR)+(RSR.K)*(DMR)+(RSR.K)*(DFD.K)+(RSR.K)*(DTR) // 15-10 16A | |
// λa.λb.λc.λd.λe.a*(b+c+d+e) | |
const uodf = (uod, dt, rrd, ssd) => uod + dt * (rrd - ssd); // p.158 15-19, L | |
const iadf = (iad, dt, srd, ssd) => iad + dt * (srd - ssd); // p.158 15-20, L | |
const stdf = (uod, dfd) => uod / dfd; // p.160 15-21, A | |
const nidf = (iad, dt) => iad / dt; // p.160 15-22, A | |
const ssdf = (std, nid) => nid >= std ? std : nid; // p.160 15-23, R | |
const dfdf = (dhd, dud, idd, iad) => dhd + dud * (idd / iad); // p.160 15-24, A | |
const iddf = (aid, rsd) => aid * rsd; // p.160 15-25, A | |
const rsdf = (rsd, dt, drd, rrd) => rsd + dt * (1 / drd) * (rrd - rsd); // p.160 15-26, L | |
const pddf = (rrd, did, idd, iad, ldd, lad, uod, und) => rrd + (1 / did) * ((idd - iad) + (ldd - lad) + (uod - und)); // p.160 15-27, R | |
const lddf = (rsd, dcd, dmd, dff, dtd) => rsd * (dcd + dmd + dff + dtd); // p.161 15-28, A | |
const ladf = (cpd, pmd, uof, mtd) => cpd + pmd + uof + mtd; // p.161 15-29, A | |
const undf = (rsd, dhd, dud) => rsd * (dhd + dud); // p.161 15-30, A | |
const cpdf = (cpd, dt, pdd, psd) => cpd + dt * (pdd - psd); // p.161 15-31, L | |
const psdf = (pdd, dcd) => DELAY3(pdd, dcd); // p.161 15-32, R | |
const pmdf = (pmd, dt, psd, rrf) => pmd + dt * (psd - rrf); // p.161 15-33, L | |
const rrff = (psd, dmd) => DELAY3(psd, dmd); // p.161 15-34, R | |
const mtdf = (mtd, dt, ssf, srd) => mtd + dt * (ssf - srd); // p.161 15-35, L | |
const srdf = (ssf, dtd) => DELAY3(ssf, dtd); // p.161 15-36, R | |
// FUNCTIONS ---------------------- | |
// TODO implement these functions correctly; see book | |
const STEP = (sth, stt) => 1; | |
const SIN = (x) => Math.sin(x); | |
const _2PI = () => Math.PI * 2; | |
const CLIP = (a,b,c,d) => 1; | |
const DELAY3 = (a,b) => 1; | |
var me, csvK, counter, bchan, beh = { | |
postConfigure: function() { | |
me = this.cnode.parent(); | |
csvK = "Distributor\nUOD.K,IAD.K,STD.K,NID.K,SSD.KL,DFD.K,IDD.K,RSD.K,PDD.KL,LDD.K,LAD.K,UND.K,CPD.K,PSD.KL,PMD.K,RRF.KL,MTD.K,SRD.KL\n"; | |
counter = 0; | |
console.log(this, this.cnode, me); | |
me.println(`\nUOD,IAD,SSD,RSD,PDD,CPD,PSD,PMD,RRF,MTD,SRD`); | |
bchan = new BroadcastChannel("proddist"); | |
bchan.onmessage = (event) => { | |
console.log(event); // this works | |
switch (event.data.signal) { | |
case 101: | |
case 202: | |
me.msg(event.data.signal, JSON.stringify(event.data.data), event.data.sender); | |
break; | |
default: break; | |
} | |
} | |
bchan.postMessage({ | |
signal: 201, | |
data: [ | |
{ | |
dtype: "RRF", | |
dval: 2.12 | |
} | |
] | |
}); | |
}, | |
processReceivedMessage: function(msg) { | |
me.println("msg received: " + msg.signal + " " + msg.data + " " + msg.sender); | |
}, | |
act: function() { | |
const arrA = [UOD.K,IAD.K,STD.K,NID.K,SSD.KL,DFD.K,IDD.K,RSD.K,PDD.KL,LDD.K,LAD.K,UND.K,CPD.K,PSD.KL,PMD.K,RRF.KL,MTD.K,SRD.KL]; | |
const arrB = arrA.map((item) => item.toFixed(4), []); | |
const csvC = arrB.join(",") + "\n"; | |
csvK += csvC; | |
UOD.K = uodf(UOD.J, DT, RRD.JK, SSD.JK); // 15-19, L | |
IAD.K = iadf(IAD.J, DT, SRD.JK, SSD.JK); // 15-10, L | |
STD.K = stdf(UOD.K, DFD.K); // 15-21, A | |
NID.K = nidf(IAD.K, DT); // 15-22, A | |
SSD.KL = ssdf(STD.K, NID.K); // 15-23, R | |
DFD.K = dfdf(DHD, DUD, IDD.K, IAD.K); // 15-24, A | |
IDD.K = iddf(AID, RSD.K); // 15-25, A | |
RSD.K = rsdf(RSD.J, DT, DRD, RRD.JK, RSD.J); // 15-26, L | |
PDD.KL = pddf(RRD.JK, DID, IDD.K, IAD.K, LDD.K, LAD.K, UOD.K, UND.K); // 15-27, R | |
LDD.K = lddf(RSD.K, DCD, DMD, DFF.K, DTD); // 15-28, A | |
LAD.K = ladf(CPD.K, PMD.K, UOF.K, MTD.K); // 15-29, A | |
UND.K = undf(RSD.K, DHD, DUD); // 15-30, A | |
CPD.K = cpdf(CPD.J, DT, PDD.JK, PSD.JK); // 15-31, L | |
PSD.KL = psdf(PDD.JK, DCD); // 15-32, R | |
PMD.K = pmdf(PMD.J, DT, PSD.JK, RRF.JK); // 15-33, L | |
RRF.KL = rrff(PSD.JK, DMD); // 15-34, R | |
MTD.K = mtdf(MTD.J, DT, SSF.JK, SRD.JK); // 15-35, L | |
SRD.KL = srdf(SSF.JK, DTD); // 15-36, R | |
if (counter++ == 5) { | |
console.log(csvK); | |
} | |
//bchan.postMessage("posting from Distribution to Retail " + counter); | |
}, | |
preAct: function() { | |
// handle the transition as the present (K) becomes the past (J) | |
// TODO some of these may be unnecessary/unused and/or may cause problems | |
RRD.JK = RRD.KL; | |
// DISTRIBUTOR - levels, rates | |
CPD.J = CPD.K; | |
IAD.J = IAD.K; | |
MTD.J = MTD.K; | |
PMD.J = PMD.K; | |
RSD.J = RSD.K; | |
UOD.J = UOD.K; | |
PDD.JK = PDD.KL; | |
PSD.JK = PSD.KL; | |
RRF.JK = RRF.KL; | |
SRD.JK = SRD.KL; | |
SSD.JK = SSD.KL; | |
}, | |
postAct: function() { | |
let dpl = 3; // number of decimal places | |
me.print(`${UOD.J.toFixed(dpl)},${IAD.J.toFixed(dpl)},${SSD.JK.toFixed(dpl)},${RSD.J.toFixed(dpl)},${PDD.JK.toFixed(dpl)},`); | |
me.print(`${CPD.J.toFixed(dpl)},${PSD.JK.toFixed(dpl)},${PMD.J.toFixed(dpl)},${RRF.JK.toFixed(dpl)},${MTD.J.toFixed(dpl)},${SRD.JK.toFixed(dpl)}`); | |
me.print("\n"); | |
/* | |
... | |
*/ | |
} | |
} | |
//# sourceURL=Distributorbehavior.js | |
]]></Distributorbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Distributor</title> | |
<rect id="ProdDistSystem/Distributor" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
<g> | |
<title>Height</title> | |
<rect id="ProdDistSystem/Distributor" fill="#6AB06A" height="50" width="10" x="80" y="0"/> | |
</g> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment