Published unlisted
Edited
Apr 5, 2019
Insert cell
Changed in both
-
md`# Monte Carlo Introduction: *Customer Service* (unfinal)`
+
md`# Monte Carlo Introduction: *Customer Service* See https://talk.observablehq.com/t/about-reactivity/1748`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Changed in fork
{ console.clear(); svg.selectAll("*").remove(); // Initialize time and time step let t = 0; let dt = 0.005; svg.append("text") .attr("x", X(0.45)) .attr("y", -marg/4) .attr("font-size", 20) .attr("id", "curTime") .text("t = " + t.toFixed(3)); // Initialize customer and server queues let q = []; let nextArrival = 0; let customerID = 0; mutable nCustLost = 0; mutable nCustServ = 0; let s =[]; for (let n=0;n<maxServers;n++) { s.push([-1,-1,Infinity, Infinity, -1]); } // Start simulation let curServers = -1; while (true) { t+=dt; svg.selectAll("#curTime").text("t=" + t.toFixed(3)); // Redraw store if params changed if (getNserv() != curServers) { curServers = getNserv(); svg.selectAll("rect").remove(); // Draw box representing the store let store = svg.append("rect") .attr("x", 0) .attr("y", 0) .attr("width", width-2*marg) .attr("height", height-2*marg) .attr("stroke", "black") .attr("stroke-width",5) .attr("fill", "none"); // Draw server stations for (let n=0;n<maxServers;n++) {
-
if (n<Nservers) {s[n][4] = 0;}
+
if (n<viewof Nservers.value) {s[n][4] = 0;}
svg.append("rect") .attr("x", X(0+stationWidth*n)) .attr("y", Y(stationHeight)) .attr("width", X(stationWidth)) .attr("height", (height-2*marg)*stationHeight) .attr("stroke", "black") .attr("stroke-width",3) .attr("fill", stationStatus(n)); } } // Check for new customer arrivals if (nextArrival <= t) { let x = Math.random()*0.8+0.1; let y = Math.random()*0.6+0.3; let curT = t; let waitTime = t+getWaitTime(); customerID+=1; q.push([x,y,curT,waitTime,customerID]); svg.append("circle") .attr("cx", X(x)) .attr("cy", Y(y)) .attr("r", 10) .attr("stroke", "transparent") .attr("fill", colorize(getAnnoyance(curT,t,waitTime))) .attr("id", 'c' + customerID); nextArrival = nextArrival+getArrTime(); console.log("Next arrival time: " + nextArrival); } // Check customer wait times and update display for (let n=0;n<q.length;n++) { // Any customers who have been waiting too long will leave the store if (q[n][3] < t) { mutable nCustLost+=1; svg.selectAll("[id=c" + q[n][4] + "]") .transition() .duration(200) .attr("r", 50) .style("fill", "red") .transition() .duration(100) .attr("r", 1) .style("fill", "transparent") .remove(); q.splice(n,1); n-=1; } // Otherwise update their color else { let a = q[n][2]; let b = q[n][3]; svg.selectAll("[id=c" + q[n][4] + "]") .attr("fill", colorize(getAnnoyance(a,t,b))); } } // Check if any customers are waiting if (q.length > 0) { let openStation = getOpenStation(s); // Check if any service stations are open if (openStation > -1) { // Get the customer who has been waiting the longest and move to the service queue let cust = q.shift(); // Determine when their service will be done cust[3] = t+getServTime(); // Compute the position of the server window cust[0] = 0.05+(openStation*stationWidth); cust[1] = stationHeight/2; // Add customer to service array s[openStation] = cust; // Animate the transition svg.selectAll("[id=c" + cust[4] + "]") .transition() .duration(1000) .attr("cx", X(cust[0])) .attr("cy", Y(cust[1])) .attr("r", 15) .style("fill", "blue"); } } // Check for customers done getting service for (let n=0;n<maxServers;n++) { if (s[n][3] < t) { mutable nCustServ+=1; svg.selectAll("[id=c" + s[n][4] + "]") .transition() .duration(200) .attr("r",50) .style("fill", "green") .transition("fill", "transparent") .duration(200) .remove(); s[n] = [-1,-1,Infinity,Infinity,0]; } } // Check if we closed any stations with customers inside! // This makes them mad and they will leave immediately.
-
for (let n=Nservers;n<maxServers;n++) {
+
for (let n=viewof Nservers.value;n<maxServers;n++) {
if (s[n][4] > 0) { mutable nCustLost+=1; svg.selectAll("[id=c" + s[n][4] + "]") .transition() .duration(200) .attr("r", 50) .style("fill", "red") .transition() .remove(); s[n] = [-1,-1,Infinity,Infinity,-1]; } } yield(svg.node().parentNode) } }
Insert cell
Insert cell
Changed in fork
function getArrTime() {
-
return expRnd(aTime);
+
return expRnd(viewof aTime.value);
}
Insert cell
Changed in fork
function getServTime() {
-
return 1+expRnd(sTime);
+
return 1+expRnd(viewof sTime.value);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Changed in fork
function stationStatus(n) {
-
if (n<Nservers) {
+
if (n<viewof Nservers.value) {
return "transparent"; } else { return "black"; } }
Insert cell
Insert cell
Insert cell
Insert cell
Changed in fork
function getNserv() {
-
return Nservers;
+
return viewof Nservers.value;
}
Insert cell