Galton board

by Nicolaus Maloney

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.23.0/ramda.js"></script>
<canvas id = 'c' width='500px' height='500px'></canvas>
https://jsfiddle.net/Zombo/qbntut9s/1/#run

JavaScript

const numRows = 10;
const numBalls = 50;
const duration = 0.1;

var canvas = new fabric.Canvas('c');

for (var numdots = 1; numdots <= numRows + 1; ++numdots) {
	for (var dotnum = 0; dotnum < numdots; ++dotnum) {
    	var dot = new fabric.Circle ({
        	radius: 5, 
        	fill: 'rgba(0, 0, 0, 1)', 
        	left: dotnum * 20 - 10 * numdots + 180, 
        	top: numdots * 15;
    	});
		canvas.add(dot);
	}
}

const balls = R.range(0, numBalls).map(i => 
    new fabric.Circle({
        radius: 5,
        // fixme: make every ball a different color
        fill: 'rgba(255, 0, 0, 1)',
        left: 170,
        top: 20,
    })
);

const stacks = {};
function flipcoin(rowNum, ballNum) {
    const ball = balls[ballNum];

    var top, left;
    var nextRow, nextBall;
    if (rowNum < numRows) {
        nextRow = rowNum + 1;
        nextBall = ballNum;
        const flip =  Math.random();
        top = '+=20';
        left;
        if (flip < 0.5) {
            left = '+=10';
        } else {
            left = '-=10';
        }
    }
    else {
        // Figure out our "absolute left" position ... get it from the
        // ball object:
        const absLeft = ball.left;
        console.log(`ball ${ballNum} finished at ${absLeft}`);
        
        // How many are in the stack already? If the `stacks` object
        // doesn't have an entry for our position, then we need to
        // initialize it to zero.
        if (!(absLeft in stacks)) stacks[absLeft] = 0;
        
        // Now, stacks[absLeft] tells how many are in the stack
        const numInStack = stacks[absLeft];
        
        // The distance we fall depends on how many balls are
        // below us in the stack
        top = '+=' + (180 - 10 * numInStack);
        
				// After this ball falls, there will be one more in the stack
        stacks[absLeft]++;
        
        left = '+=0';
        nextRow = 0;
        nextBall = ballNum + 1;
        if (nextBall < numBalls)...