let SVG_DX = 800,
N_COLS = 56,
CELL_DIM = 10;
(function addArrayEqualityMethod() {
// from http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
Array.prototype.equals = function (array) {
for (var i = 0, l=this.length; i < l; i++) {
if (this[i] != array[i]) {
return false;
}
}
return true;
}
})();
function assignClass(cell) {
return "row_" + cell.row + (cell.state == 1 ? " state_1" : " state_0");
}
function computeNewState(states) {
// state of first cell remains 0
let new_states = [0];
// NB: loop begins at second element in array and end at second
// to last element in array; state for first and last elements
// in array remain 0
for (let i = 1; i < states.length - 1; i++) {
// NB: slice end not included
let context = states.slice(i - 1, i + 2);
// rule 126
if (context.equals([1, 1, 1])) {
new_states.push(0);
} else if (context.equals([1, 1, 0])) {
new_states.push(1);
} else if (context.equals([1, 0, 1])) {
new_states.push(1);
} else if (context.equals([1, 0, 0])) {
new_states.push(1);
} else if (context.equals([0, 1, 1])) {
new_states.push(1);
} else if (context.equals([0, 1, 0])) {
new_states.push(1);
} else if (context.equals([0, 0, 1])) {
new_states.push(1);
} else if (context.equals([0, 0, 0])) {
new_states.push(0);
}
}
// state of last cell remains 0
new_states.push(0);
return new_states;
}
function updateRow(selection, plot, row) {
let old_states = selection.data().map(cell => cell.state),
new_states = computeNewState(old_states);
if (plot == "single") {
updateThisRow(selection, new_states);
}
if (plot == "multi") {
updateNextRow(new_states, row);
}
}
function updateThisRow(selection, new_states) {
selection.each(function(cell, i) {
cell.state = new_states[i];
d3.select(this)
.attr("class", assignClass);
});
}
function updateNextRow(new_states, row) {
d3.select("#plot_multi")
.selectAll(".row_" + (row + 1))
.each(function(cell, i) {
cell.state = new_states[i];
d3.select(this)
.transition()
.delay(row * 50)
.attr("class", assignClass);
});
}
function constructCells(n_rows) {
let rows = d3.range(n_rows),
cols = d3.range(N_COLS),
cells = d3.cross(rows, cols, (row, col) => {
return {"row": row, "col": col, "state": 0};
});
// set initial state of cell in first row, center col to 1
cells[Math.round(N_COLS/2)].state = 1;
return cells;
}
function addSVG(plot, svg_dy) {
d3.select("#plot_" + plot)
.append("svg")
.attr("id", "svg_" + plot)
.attr("width", SVG_DX)
.attr("height", svg_dy);
}
function plotRects(plot, cell) {
d3.select("#svg_" + plot)
.selectAll("rect")
.data(cell)
.enter()
.append("rect")
.attr("class", assignClass)
.attr("height", CELL_DIM + "px")
.attr("width", CELL_DIM + "px")
.attr("x", cell => cell.col * 11)
.attr("y", cell => cell.row * 11);
}
function clearStates(plot) {
d3.select("#plot_" + plot)
.selectAll("rect")
.each(function(cell) {
cell.row == 0 && cell.col == Math.round(N_COLS/2) ? cell.state = 1 : cell.state = 0;
d3.select(this)
.attr("class", assignClass);
});
}