function buildCircles(context, data, y, extraY1, extraY2, color) {
let x = halfDeltaX;
for(let i = 0; i < data.length; i++) {
let curX = x;
let simulation = d3.forceSimulation(data[i])
.force('charge', d3.forceManyBody().strength(0))
.force('collision', d3.forceCollide().radius(radius + spacing))
.force('x', d3.forceX().x( curX ))
.force('y', d3.forceY().y( (d) => y(d['Happiness Score']) ))
simulation.on('tick', () => {
const delaunay = d3.Delaunay.from(data[i], d => d.x, d => d.y);
const bounds = [
curX - halfDeltaX + 0.5,
y.range()[1] + 0.5 + extraY1,
curX + halfDeltaX - 0.5,
y.range()[0] - 0.5 + extraY2
];
const voronoi = delaunay.voronoi(bounds);
context.clearRect(bounds[0], bounds[1], bounds[2] - bounds[0], bounds[3] - bounds[1]);
for(let j = 0; j < data[i].length; j++) {
let alpha = (data[i][j]['Happiness Score'] - y.domain()[0]) / (y.domain()[1] - y.domain()[0]);
context.fillStyle = color(alpha);
context.beginPath();
voronoi.renderCell(j, context);
context.fill();
}
context.beginPath();
voronoi.render(context);
voronoi.renderBounds(context);
context.strokeStyle = '#ccc';
context.stroke();
context.beginPath();
context.fillStyle = 'white';
delaunay.renderPoints(context);
context.fill();
})
x += deltaX;
}
}