{
var {seat,start,startLimit,radius,new_fall_delay,circles_per_fall,exitAmt,duration} = config;
var iterations = 0;
var padding = radius*3;
var data = dataGenerator();
const rectCircles = pack(Array.from({length: (start-startLimit)}, () => ({r: radius*2 })),padding);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
var sim = d3.forceSimulation(data)
.force("y",d3.forceY(d => {
return d.side === "down" ? seat : -height+Math.random()*height-10;
}))
.force("collide", d3.forceCollide(padding))
sim.on('tick', function() {
svg
.selectAll(".sim-circles")
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.style('fill', d => color(d.x))
.style('stroke', d => color(d.x));
});
function draw_circles() {
svg
.selectAll(".sim-circles")
.data(data)
.join(
enter => enter.append("circle")
.attr("class","sim-circles")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", radius),
exit => exit.remove()
);
}
function add_circles() {
if (iterations < duration) {
data = data.filter(d => d.side != "up");
if (iterations > 0) {
var righties = [...data].filter(d => d.side !== "up").slice(0,exitAmt);
righties.forEach(function(d,i){
d.side = "up";
});
}
for (let i = 0; i < circles_per_fall; ++i) {
data.push({
x: randn_bm()*width/2+width/4,
y: height+(height*0.9*Math.random()),
vx: 0,
vy: 0,
side:"down"
});
}
draw_circles();
sim.nodes(data).alpha(0.9).velocityDecay(0.4);
}
iterations++;
}
draw_circles();
d3.interval(add_circles, new_fall_delay);
return svg.node();
}