Skip to content

Instantly share code, notes, and snippets.

@kenwebb
Last active December 3, 2024 18:19
Show Gist options
  • Save kenwebb/105e5059b60bde86f5ddc6f1b5e44def to your computer and use it in GitHub Desktop.
Save kenwebb/105e5059b60bde86f5ddc6f1b5e44def to your computer and use it in GitHub Desktop.
Industrial Dynamics - Chapter 15 - Xholonish - Distributor
<?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