raywo/MMM-GameOfLife

View on GitHub
MMM-GameOfLife.js

Summary

Maintainability
D
1 day
Test Coverage
"use strict";
 
Module.register("MMM-GameOfLife", {
 
// Default module config.
defaults: {
name: "MMM-GameOfLife",
 
desiredFrameRate: 1,
resolution: 10,
canvasWidth: 300,
canvasHeight: 300,
notAliveColorCode: "#000",
aliveColorCode: "#aaa"
},
 
 
start: function() {
Log.info("Starting module: " + this.name);
this.sanitizeConfig();
},
 
 
getDom: function() {
let wrapper = document.createElement("div");
wrapper.id = "gameOfLifeWrapper";
 
return wrapper;
},
 
getScripts: function() {
return [
"https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js"
];
},
 
 
notificationReceived: function(notification, payload, sender) {
if (notification === "DOM_OBJECTS_CREATED") {
Log.info("DOM objects are created. Starting P5 …");
 
let sketch = this.makeSketch(this.config);
new p5(sketch, "gameOfLifeWrapper");
}
},
 
 
sanitizeConfig: function() {
if (this.config.desiredFrameRate < 1) {
this.config.desiredFrameRate = 1;
}
 
if (this.config.resolution < 2) {
this.config.resolution = 2;
}
 
if (this.config.canvasWidth < 50) {
this.config.canvasWidth = 50;
}
 
if (this.config.canvasHeight < 50) {
this.config.canvasHeight = 50;
}
},
 
 
Function `makeSketch` has a Cognitive Complexity of 63 (exceeds 5 allowed). Consider refactoring.
Function `makeSketch` has 112 lines of code (exceeds 25 allowed). Consider refactoring.
makeSketch: function(conf) {
return function(pFive) {
let currentGenGrid;
let lastGenGrid;
 
/* user definable parameters */
let desiredFrameRate = conf.desiredFrameRate;
let resolution = conf.resolution;
let canvasWidth = conf.canvasWidth;
let canvasHeight = conf.canvasHeight;
let notAliveColorCode = conf.notAliveColorCode;
let aliveColorCode = conf.aliveColorCode;
let notAliveColor = getNotAliveColor(notAliveColorCode);
 
/* computed parameters */
let rows = canvasWidth / resolution;
let cols = canvasHeight / resolution;
 
 
pFive.setup = function() {
pFive.frameRate(desiredFrameRate);
pFive.createCanvas(canvasWidth, canvasHeight);
 
lastGenGrid = makeGrid(rows, cols);
currentGenGrid = makeGrid(rows, cols);
fillGridRandomly(currentGenGrid);
};
 
 
pFive.draw = function() {
pFive.clear();
pFive.background(notAliveColor);
 
drawGrid(currentGenGrid);
let nextGenGrid = computeNextGeneration(currentGenGrid);
 
if (representingSameState(nextGenGrid, currentGenGrid) || representingSameState(nextGenGrid, lastGenGrid)) {
fillGridRandomly(currentGenGrid);
} else {
lastGenGrid = currentGenGrid;
currentGenGrid = nextGenGrid;
}
};
 
 
/*
"Private functions"
*/
 
function getNotAliveColor() {
if (notAliveColorCode === "transparent") {
return pFive.color("rgba(0, 0, 0, 0)");
} else {
return pFive.color(notAliveColorCode);
}
}
 
 
function makeGrid(rows, cols) {
let array = new Array(rows);
 
for (let i = 0; i < rows; i++) {
array[i] = new Array(cols);
}
 
return array;
}
 
 
function fillGridRandomly(grid) {
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[i].length; j++) {
grid[i][j] = pFive.floor(pFive.random(2));
}
}
}
 
 
function drawGrid(grid) {
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[i].length; j++) {
drawCell(grid, i, j);
}
}
}
 
 
function drawCell(grid, i, j) {
let aliveColor = pFive.color(aliveColorCode);
 
if (grid[i][j] === 1) {
pFive.fill(aliveColor);
pFive.stroke(aliveColor);
 
let x = i * resolution;
let y = j * resolution;
pFive.rect(x, y, resolution - 1, resolution - 1);
}
}
 
 
function computeNextGeneration(currentGen) {
let nextGen = makeGrid(rows, cols);
 
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
computeNextGenCell(i, j, currentGen, nextGen);
}
}
 
return nextGen;
}
 
 
function computeNextGenCell(i, j, currentGen, nextGen) {
let currentState = currentGen[i][j];
let aliveNeighbors = countAliveNeighbors(currentGen, i, j);
 
if (currentState === 0 && aliveNeighbors === 3) {
nextGen[i][j] = 1;
} else if (currentState === 1 && (aliveNeighbors < 2 || aliveNeighbors > 3)) {
nextGen[i][j] = 0;
} else {
nextGen[i][j] = currentState;
}
}
 
 
function countAliveNeighbors(grid, x, y) {
let count = 0;
 
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
let row = (x + i + rows) % rows;
let col = (y + j + cols) % cols;
 
count += grid[row][col];
}
}
 
count -= grid[x][y];
 
return count;
}
 
 
function representingSameState(leftGrid, rightGrid) {
for (let i = 0; i < leftGrid.length; i++) {
for (let j = 0; j < leftGrid.length; j++) {
if (leftGrid[i][j] !== rightGrid[i][j]) {
return false;
}
}
}
 
return true;
}
};
}
});