element
+// var goltable = document.createElement("tbody");
+//
+// // build Table HTML
+// var tablehtml = '';
+// for (var h = 0; h < this.height; h++) {
+// tablehtml += "
";
+// for (var w = 0; w < this.width; w++) {
+// tablehtml += "
";
+// }
+// tablehtml += "
";
+// }
+// goltable.innerHTML = tablehtml;
+//
+// // add table to the #board element
+// var board = document.getElementById('board');
+// board.appendChild(goltable);
+//
+// // once html elements are added to the page, attach events to them
+// this.setupBoardEvents();
+// },
+//
+// forEachCell: function (iteratorFunc) {
+// /*
+// Write forEachCell here. You will have to visit
+// each cell on the board, call the "iteratorFunc" function,
+// and pass into func, the cell and the cell's x & y
+// coordinates. For example: iteratorFunc(cell, x, y)
+// */
+// var board = document.getElementById('board').firstChild
+// Array.prototype.slice.call(board.children).forEach(function (row) {
+// Array.prototype.slice.call(row.children).forEach(function (cell) {
+// var coords = cell.id.split("-")
+// var x = parseInt(coords[0])
+// var y = parseInt(coords[1])
+// iteratorFunc(cell, x, y)
+// })
+// })
+//
+// },
+//
+// setupBoardEvents: function () {
+// // each board cell has an CSS id in the format of: "x-y"
+// // where x is the x-coordinate and y the y-coordinate
+// // use this fact to loop through all the ids and assign
+// // them "on-click" events that allow a user to click on
+// // cells to setup the initial state of the game
+// // before clicking "Step" or "Auto-Play"
+//
+// // clicking on a cell should toggle the cell between "alive" & "dead"
+// // for ex: an "alive" cell be colored "blue", a dead cell could stay white
+//
+// // EXAMPLE FOR ONE CELL
+// // Here is how we would catch a click event on just the 0-0 cell
+// // You need to add the click event on EVERY cell on the board
+//
+// var onCellClick = function (e) {
+// // QUESTION TO ASK YOURSELF: What is "this" equal to here?
+//
+// // how to set the style of the cell when it's clicked
+// if (this.getAttribute('data-status') == 'dead') {
+// this.className = "alive";
+// this.setAttribute('data-status', 'alive');
+// this.setAttribute('style', 'background-color:' + color)
+// // console.log(color)
+// } else {
+// this.className = "dead";
+// this.setAttribute('data-status', 'dead');
+// this.setAttribute('style', 'background-color:#FFFFFF')
+// }
+// };
+// this.forEachCell(function (cell) {
+// cell.onclick = onCellClick
+// })
+// // var cell00 = document.getElementById('0-0');
+// // cell00.onclick = onCellClick;
+// },
+//
+// // sound: function (sines, interval) {
+// // var env = T("adsr", {
+// // d: 3000,
+// // s: 0,
+// // r: 600
+// // });
+// //
+// // T("perc", {
+// // r: interval * 0.5
+// // }, T("reverb", {
+// // room: 0.95,
+// // damp: 0.1,
+// // mix: 0.75
+// // }, sines)).on("ended", function () {
+// // this.pause();
+// // }).bang().play();
+// // },
+//
+// // makeSine: function (cell) {
+// // return T("saw", {
+// // freq: pentatonicFrequencies[freq],
+// // mul: amplitude
+// // });
+// // },
+//
+// step: function () {
+// color = '#'+Math.floor(Math.random()*16777215).toString(16)
+// // console.log(this.color)
+// // Here is where you want to loop through all the cells
+// // on the board and determine, based on it's neighbors,
+// // whether the cell should be dead or alive in the next
+// // evolution of the game.
+// //
+// // You need to:
+// // 1. Count alive neighbors for all cells
+// // 2. Set the next state of all cells based on their alive neighbors
+// // (x, y) -> (1, 1)
+// // check:
+// // (0, 0) , (1, 0) , (2, 0)
+// // (0, 1) , , (2, 1)
+// // (0, 2) , (1, 2) , (2, 2)
+// //
+// // (x-1, y-1), ( x , y-1), (x+1, y-1)
+// // (x-1, y ), ( x , y ), (x+1, y )
+// // (x-1, y+1), ( x , y+1), (x+1, y+1)
+// //
+// //
+// var self = this;
+// var start = Date.now(),
+// cells = [],
+// boardWidth = this.width,
+// boardHeight = this.height
+// this.forEachCell(function (cell, x, y) {
+// // console.log(cell)
+// var cellObj = new Cell(cell, x, y, cell.dataset.status, 0, 0, boardHeight, boardWidth)
+// for (var i = cellObj.x - 1; i < cellObj.x + 2; i++) {
+// // if (i < 0 || i > boardWidth - 1) continue
+// var col = i < 0 ? boardWidth - 1 : i % boardWidth
+// for (var j = cellObj.y - 1; j < cellObj.y + 2; j++) {
+// if (i === cellObj.x && j === cellObj.y) continue
+// var row = j < 0 ? boardHeight - 1 : j % boardHeight
+// var currCell = document.getElementById(col + '-' + row)
+// if (currCell.dataset.status === 'alive') cellObj.aliveCount++
+// if (currCell.dataset.status === 'dead') cellObj.deadCount++
+// }
+// }
+// cells.push(cellObj)
+// })
+//
+// var sines = [];
+//
+// // var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
+// // var rule = document.styleSheets[1][cssRuleCode];
+// // document.styleSheets[1].insertRule('td.alive' + ' {'+'background-color'+':'+
+// // '#'+Math.floor(Math.random()*16777215).toString(16) +'}', 1)
+// // var selector = rule.selectorText; //maybe '#tId'
+// // console.log(selector)
+// // var value = rule.value; //both selectorText and value are settable
+//
+// cells.forEach(function (cellObj) {
+// if (cellObj.status === 'alive') {
+// if (cellObj.aliveCount < 2 || cellObj.aliveCount > 3) {
+// cellObj.cell.click()
+// }
+// synth.noteOnWithFreq(cellObj.freq, cellObj.velocity);
+// }
+// if (cellObj.status === 'dead') {
+// if (cellObj.aliveCount === 3) {
+// cellObj.cell.click()
+// }
+// synth.noteOffWithFreq(cellObj.freq);
+// }
+// })
+// },
+//
+// enableAutoPlay: function () {
+// // Start Auto-Play by running the 'step' function
+// // automatically repeatedly every fixed time interval
+// if (this.autoPlayOn) {
+// this.autoPlayOn = false
+// clearInterval(this.setIntervalID)
+// document.getElementById('play_btn').innerHTML = 'Play'
+// } else {
+// this.autoPlayOn = true
+// this.setIntervalID = setInterval(this.step.bind(this), document.getElementById('step_amount').value || 100)
+// document.getElementById('play_btn').innerHTML = 'Pause'
+// }
+// },
+//
+// clear: function () {
+// this.forEachCell(function (cell) {
+// cell.className = "dead";
+// cell.setAttribute('data-status', 'dead');
+// })
+// },
+//
+// randomize: function () {
+// this.forEachCell(function (cell, x, y) {
+// var state = Math.floor(Math.random() * 2)
+// if (state === 1) {
+// cell.className = "dead"
+// cell.setAttribute('data-status', 'dead');
+// } else {
+// cell.className = 'alive'
+// cell.setAttribute('data-status', 'alive');
+// }
+// })
+//
+// }
+// };
+// var FileReader = new FileReader()
+// document.getElementById('step_btn').addEventListener('click', gameOfLife.step.bind(gameOfLife))
+// document.getElementById('clear_btn').addEventListener('click', gameOfLife.clear.bind(gameOfLife))
+// document.getElementById('play_btn').addEventListener('click', gameOfLife.enableAutoPlay.bind(gameOfLife))
+// document.getElementById('reset_btn').addEventListener('click', gameOfLife.randomize.bind(gameOfLife))
+// document.getElementById('submit_file').addEventListener('click', function () {
+// debugger;
+// var file = document.getElementById('input').files[0],
+// content = FileReader.readAsText(file)
+// while (FileReader.readyState !== 2) {
+// console.log(FileReader.readyState)
+// }
+// console.log(content.result)
+// })
+//
+// gameOfLife.createAndShowBoard();
+//
+// function Cell(cell, x, y, status, deadCount, aliveCount, height, width) {
+// this.cell = cell
+// this.x = x
+// this.y = y
+// this.status = status
+// this.deadCount = deadCount
+// this.aliveCount = aliveCount
+// this.freq = pentatonicFrequencies[x % pentatonicFrequencies.length];
+// this.velocity = 1000* (y / width);
+// }
diff --git a/app/index.html b/app/index.html
new file mode 100644
index 0000000..fc0ee59
--- /dev/null
+++ b/app/index.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+ Grains of Life
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
element
- var goltable = document.createElement("tbody");
-
- // build Table HTML
- var tablehtml = '';
- for (var h = 0; h < this.height; h++) {
- tablehtml += "
";
- for (var w = 0; w < this.width; w++) {
- tablehtml += "
";
- }
- tablehtml += "
";
- }
- goltable.innerHTML = tablehtml;
-
- // add table to the #board element
- var board = document.getElementById('board');
- board.appendChild(goltable);
-
- // once html elements are added to the page, attach events to them
- this.setupBoardEvents();
- },
-
- forEachCell: function (iteratorFunc) {
- /*
- Write forEachCell here. You will have to visit
- each cell on the board, call the "iteratorFunc" function,
- and pass into func, the cell and the cell's x & y
- coordinates. For example: iteratorFunc(cell, x, y)
- */
- var board = document.getElementById('board').firstChild
- Array.prototype.slice.call(board.children).forEach(function (row) {
- Array.prototype.slice.call(row.children).forEach(function (cell) {
- var coords = cell.id.split("-")
- var x = parseInt(coords[0])
- var y = parseInt(coords[1])
- iteratorFunc(cell, x, y)
- })
- })
-
- },
-
- setupBoardEvents: function () {
- // each board cell has an CSS id in the format of: "x-y"
- // where x is the x-coordinate and y the y-coordinate
- // use this fact to loop through all the ids and assign
- // them "on-click" events that allow a user to click on
- // cells to setup the initial state of the game
- // before clicking "Step" or "Auto-Play"
-
- // clicking on a cell should toggle the cell between "alive" & "dead"
- // for ex: an "alive" cell be colored "blue", a dead cell could stay white
-
- // EXAMPLE FOR ONE CELL
- // Here is how we would catch a click event on just the 0-0 cell
- // You need to add the click event on EVERY cell on the board
-
- var onCellClick = function (e) {
- // QUESTION TO ASK YOURSELF: What is "this" equal to here?
-
- // how to set the style of the cell when it's clicked
- if (this.getAttribute('data-status') == 'dead') {
- this.className = "alive";
- this.setAttribute('data-status', 'alive');
- this.setAttribute('style', 'background-color:' + color)
- // console.log(color)
- } else {
- this.className = "dead";
- this.setAttribute('data-status', 'dead');
- this.setAttribute('style', 'background-color:#FFFFFF')
- }
- };
- this.forEachCell(function (cell) {
- cell.onclick = onCellClick
- })
- // var cell00 = document.getElementById('0-0');
- // cell00.onclick = onCellClick;
- },
-
- // sound: function (sines, interval) {
- // var env = T("adsr", {
- // d: 3000,
- // s: 0,
- // r: 600
- // });
- //
- // T("perc", {
- // r: interval * 0.5
- // }, T("reverb", {
- // room: 0.95,
- // damp: 0.1,
- // mix: 0.75
- // }, sines)).on("ended", function () {
- // this.pause();
- // }).bang().play();
- // },
-
- // makeSine: function (cell) {
- // return T("saw", {
- // freq: pentatonicFrequencies[freq],
- // mul: amplitude
- // });
- // },
-
- step: function () {
- color = '#'+Math.floor(Math.random()*16777215).toString(16)
- // console.log(this.color)
- // Here is where you want to loop through all the cells
- // on the board and determine, based on it's neighbors,
- // whether the cell should be dead or alive in the next
- // evolution of the game.
- //
- // You need to:
- // 1. Count alive neighbors for all cells
- // 2. Set the next state of all cells based on their alive neighbors
- // (x, y) -> (1, 1)
- // check:
- // (0, 0) , (1, 0) , (2, 0)
- // (0, 1) , , (2, 1)
- // (0, 2) , (1, 2) , (2, 2)
- //
- // (x-1, y-1), ( x , y-1), (x+1, y-1)
- // (x-1, y ), ( x , y ), (x+1, y )
- // (x-1, y+1), ( x , y+1), (x+1, y+1)
- //
- //
- var self = this;
- var start = Date.now(),
- cells = [],
- boardWidth = this.width,
- boardHeight = this.height
- this.forEachCell(function (cell, x, y) {
- // console.log(cell)
- var cellObj = new Cell(cell, x, y, cell.dataset.status, 0, 0, boardHeight, boardWidth)
- for (var i = cellObj.x - 1; i < cellObj.x + 2; i++) {
- // if (i < 0 || i > boardWidth - 1) continue
- var col = i < 0 ? boardWidth - 1 : i % boardWidth
- for (var j = cellObj.y - 1; j < cellObj.y + 2; j++) {
- if (i === cellObj.x && j === cellObj.y) continue
- var row = j < 0 ? boardHeight - 1 : j % boardHeight
- var currCell = document.getElementById(col + '-' + row)
- if (currCell.dataset.status === 'alive') cellObj.aliveCount++
- if (currCell.dataset.status === 'dead') cellObj.deadCount++
- }
- }
- cells.push(cellObj)
- })
-
- var sines = [];
-
- // var cssRuleCode = document.all ? 'rules' : 'cssRules'; //account for IE and FF
- // var rule = document.styleSheets[1][cssRuleCode];
- // document.styleSheets[1].insertRule('td.alive' + ' {'+'background-color'+':'+
- // '#'+Math.floor(Math.random()*16777215).toString(16) +'}', 1)
- // var selector = rule.selectorText; //maybe '#tId'
- // console.log(selector)
- // var value = rule.value; //both selectorText and value are settable
-
- cells.forEach(function (cellObj) {
- if (cellObj.status === 'alive') {
- if (cellObj.aliveCount < 2 || cellObj.aliveCount > 3) {
- cellObj.cell.click()
- }
- synth.noteOnWithFreq(cellObj.freq, cellObj.velocity);
- }
- if (cellObj.status === 'dead') {
- if (cellObj.aliveCount === 3) {
- cellObj.cell.click()
- }
- synth.noteOffWithFreq(cellObj.freq);
- }
- })
- },
-
- enableAutoPlay: function () {
- // Start Auto-Play by running the 'step' function
- // automatically repeatedly every fixed time interval
- if (this.autoPlayOn) {
- this.autoPlayOn = false
- clearInterval(this.setIntervalID)
- document.getElementById('play_btn').innerHTML = 'Play'
- } else {
- this.autoPlayOn = true
- this.setIntervalID = setInterval(this.step.bind(this), document.getElementById('step_amount').value || 100)
- document.getElementById('play_btn').innerHTML = 'Pause'
- }
- },
-
- clear: function () {
- this.forEachCell(function (cell) {
- cell.className = "dead";
- cell.setAttribute('data-status', 'dead');
- })
- },
-
- randomize: function () {
- this.forEachCell(function (cell, x, y) {
- var state = Math.floor(Math.random() * 2)
- if (state === 1) {
- cell.className = "dead"
- cell.setAttribute('data-status', 'dead');
- } else {
- cell.className = 'alive'
- cell.setAttribute('data-status', 'alive');
- }
- })
-
- }
-};
-var FileReader = new FileReader()
-document.getElementById('step_btn').addEventListener('click', gameOfLife.step.bind(gameOfLife))
-document.getElementById('clear_btn').addEventListener('click', gameOfLife.clear.bind(gameOfLife))
-document.getElementById('play_btn').addEventListener('click', gameOfLife.enableAutoPlay.bind(gameOfLife))
-document.getElementById('reset_btn').addEventListener('click', gameOfLife.randomize.bind(gameOfLife))
-document.getElementById('submit_file').addEventListener('click', function () {
- debugger;
- var file = document.getElementById('input').files[0],
- content = FileReader.readAsText(file)
- while (FileReader.readyState !== 2) {
- console.log(FileReader.readyState)
- }
- console.log(content.result)
-})
-
-gameOfLife.createAndShowBoard();
-
-function Cell(cell, x, y, status, deadCount, aliveCount, height, width) {
- this.cell = cell
- this.x = x
- this.y = y
- this.status = status
- this.deadCount = deadCount
- this.aliveCount = aliveCount
- this.freq = pentatonicFrequencies[x % pentatonicFrequencies.length];
- this.velocity = 1000* (y / width);
-}
diff --git a/package.json b/package.json
index 24d4755..cf557f1 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "",
"scripts": {
- "start": "echo 'please select start file'",
+ "start": "nodemon server.js",
"test": "nodemon -x mocha ./tests/index.spec.js"
},
"repository": {
@@ -13,7 +13,11 @@
"author": "",
"license": "ISC",
"dependencies": {
- "nodemon": "^1.9.2"
+ "body-parser": "^1.15.1",
+ "express": "^4.13.4",
+ "express-session": "^1.13.0",
+ "nodemon": "^1.9.2",
+ "timbre": "^14.11.25"
},
"devDependencies": {
"mocha": "^2.5.3",
@@ -22,8 +26,5 @@
"bugs": {
"url": "https://github.com/Octowl/GrainsOfLife/issues"
},
- "homepage": "https://github.com/Octowl/GrainsOfLife#readme",
- "dependencies": {
- "timbre": "^14.11.25"
- }
+ "homepage": "https://github.com/Octowl/GrainsOfLife#readme"
}
diff --git a/libraries/bootstrap.min.css b/public/css/bootstrap.min.css
similarity index 100%
rename from libraries/bootstrap.min.css
rename to public/css/bootstrap.min.css
diff --git a/game.css b/public/css/game.css
similarity index 100%
rename from game.css
rename to public/css/game.css
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..683cb19
--- /dev/null
+++ b/server.js
@@ -0,0 +1,20 @@
+'use strict';
+var express = require("express");
+var app = express();
+var bodyParser = require("body-parser");
+var session = require("express-session");
+
+// PUBLIC ROUTES
+ app.use('/app', express.static(__dirname + "/app"))
+ app.use('/files/libraries', express.static(__dirname + "/libraries"))
+ app.use('/files', express.static(__dirname + "/public"))
+ app.use('/files', express.static(__dirname + "/bower_components"))
+ app.use('/files/bootstrap', express.static(__dirname + "/bower_components/bootstrap/dist"))
+ app.use('/files/bootstrap/slider', express.static(__dirname + "/bower_components/bootstrap-slider"))
+
+// dynamic routes
+app.get("/", (req, res, next) => res.status(200).sendFile(__dirname + "/app/index.html"))
+
+app.listen(1133, ()=>console.log("listening on 1133"));
+
+module.exports = app;
diff --git a/tests/index.spec.js b/tests/index.spec.js
index 498b5e1..669cefd 100644
--- a/tests/index.spec.js
+++ b/tests/index.spec.js
@@ -1,58 +1,121 @@
const should = require('chai').should();
-xdescribe("Grains of Life", function(){
+describe("Grains of Life", function(){
+ it("is refactored to Angular best practices", function () {
+ throw 'fail';
+ })
describe("Grid", function () {
describe("Game Logic", function () {
//Game of Life Rules: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules
- it("follows game of life rules")
+ it("follows game of life rules", function(){
+ //throw 'false';
+ })
})
describe("Node", function () {
describe("State", function () {
- it("can be 'alive' or 'dead'")
- it("is 'dead' by default")
+ it("can be 'alive' or 'dead'", function(){
+ //throw 'fail';
+ })
+ it("is 'dead' by default", function(){
+ //throw 'fail';
+ })
})
describe("Wave", function () {
- it("outputs when Node is alive")
- it("does not output when Node is dead")
- it("is function of coordinates")
- it("frequency is controlled by x coords by default")
- it("amplitude (volume) is controlled by y coords by default")
- it("has a different form for every node")
- it("outputs to a processor chain")
+ it("outputs when Node is alive", function(){
+ throw 'fail';
+ })
+ it("does not output when Node is dead", function(){
+ throw 'fail';
+ })
+ it("is function of coordinates", function(){
+ throw 'fail';
+ })
+ it("frequency is controlled by x coords by default", function(){
+ throw 'fail';
+ })
+ it("amplitude (volume) is controlled by y coords by default", function(){
+ throw 'fail';
+ })
+ it("has a different form for every node", function(){
+ throw 'fail';
+ })
+ it("outputs to a processor chain", function(){
+ throw 'fail';
+ })
})
describe("Click", function () {
- it("toggles between 'alive' and 'dead'")
- it("plays a short tone")
+ it("toggles between 'alive' and 'dead'", function(){
+ //throw 'fail';
+ })
+ it("plays a short tone", function(){
+ throw 'fail';
+ })
})
})
describe("Play Button", function () {
- it("plays the sounds continuously")
- it("iterates the game state")
- it("changes to pause button when running")
+ it("plays the sounds continuously", function(){
+ throw 'fail';
+ })
+ it("iterates the game state", function(){
+ throw 'fail';
+ })
+ it("changes to pause button when running", function(){
+ throw 'fail';
+ })
describe("Pause Button", function () {
- it("pauses both playback and game play")
+ it("pauses both playback and game play", function(){
+ throw 'fail';
+ })
})
})
describe("Save Button", function () {
- it("creates a persistent route the the current grid state")
- it("gives some sort of visual feedback")
+ it("creates a persistent route the the current grid state", function(){
+ throw 'fail';
+ })
+ it("gives some sort of visual feedback", function(){
+ throw 'fail';
+ })
})
describe("UI Controller", function () {
- it("controls width")
- it("controls height")
- it("controls wave function")
- it("controls the playback speed")
+ it("controls width", function(){
+ throw 'fail';
+ })
+ it("controls height", function(){
+ throw 'fail';
+ })
+ it("controls wave function", function(){
+ throw 'fail';
+ })
+ it("controls the playback speed", function(){
+ throw 'fail';
+ })
+ it("allows user to choose waveform", function(){
+ throw 'fail';
+ })
})
describe("Audio Output", function () {
- it("uses web audio api")
- it("combines the sounds of all nodes")
+ xit("uses web audio api", function(){
+ throw 'fail';
+ })
+ it("combines the sounds of all nodes", function(){
+ //throw 'fail';
+ })
})
})
// wish list is for features that would be cool but aren't for the first round
describe("Wish List", function () {
- it("is multiplayer")
- it("could have other custom 'alive' states (not by default)")
- it("can sample an mp3")
+ it("is multiplayer", function(){
+ throw 'fail';
+ })
+ it("could have other custom 'alive' states (not by default)", function(){
+ throw 'fail';
+ })
+ it("can sample an mp3", function(){
+ throw 'fail';
+ })
+ it("does not slow down with more live nodes", function(){
+ throw 'fail';
+ })
})
})