stub out stream for Cell
This commit is contained in:
parent
f46b72f6db
commit
530acc0aeb
6 changed files with 96 additions and 13 deletions
|
@ -11,17 +11,57 @@ class Cell {
|
||||||
}
|
}
|
||||||
setLiving() {
|
setLiving() {
|
||||||
if (this.living && this.liveNeighbors !== 2 && this.liveNeighbors !== 3) {
|
if (this.living && this.liveNeighbors !== 2 && this.liveNeighbors !== 3) {
|
||||||
|
this.liveNeighbors = 0;
|
||||||
return (this.living = false);
|
return (this.living = false);
|
||||||
}
|
}
|
||||||
if (this.liveNeighbors === 3) {
|
if (this.liveNeighbors === 3) {
|
||||||
|
this.liveNeighbors = 0;
|
||||||
return (this.living = true);
|
return (this.living = true);
|
||||||
}
|
}
|
||||||
|
this.liveNeighbors = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Stream {
|
||||||
|
constructor(head, next) {
|
||||||
|
this.head = head;
|
||||||
|
this.tail = next;
|
||||||
|
this.memo = false;
|
||||||
|
}
|
||||||
|
get next() {
|
||||||
|
if (!this.memo) {
|
||||||
|
this.tail = this.tail();
|
||||||
|
this.memo = true;
|
||||||
|
}
|
||||||
|
return this.tail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CellStream extends Stream {
|
||||||
|
constructor(head, next) {
|
||||||
|
super(head, next);
|
||||||
|
}
|
||||||
|
get living() {
|
||||||
|
return this.head.living;
|
||||||
|
}
|
||||||
|
set liveNeighbors(liveNeighbors) {
|
||||||
|
this.head.liveNeighbors = liveNeighbors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cellStream = (living = false, liveNeighbors = 0) => {
|
||||||
|
return new CellStream(new Cell(living, liveNeighbors), function () {
|
||||||
|
this.head.setLiving();
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// as a stream -> cellStream = Stream(Cell, () => Cell(cellStream.isLiving()))
|
// as a stream -> cellStream = Stream(Cell, () => Cell(cellStream.isLiving()))
|
||||||
// in this case GameField = { [x-y]: cellStream }
|
// in this case GameField = { [x-y]: cellStream }
|
||||||
// communicating with neighbors = filter for (Boolean(Cell.living)) -> Cell neighbors.addLivingNeighbor
|
// communicating with neighbors = filter for (Boolean(Cell.living)) -> Cell neighbors.addLivingNeighbor
|
||||||
// controlling whether to call or not: filter for (Boolean(Cell.living) || Boolean(cell.liveNeighbors)) -> cellStream.next
|
// controlling whether to call or not: filter for (Boolean(Cell.living) || Boolean(cell.liveNeighbors)) -> cellStream.next
|
||||||
|
|
||||||
module.exports = Cell;
|
module.exports = {
|
||||||
|
Cell,
|
||||||
|
cellStream,
|
||||||
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Cell from "./Cell";
|
import { cellStream } from "./Cell";
|
||||||
|
|
||||||
export default class GameField {
|
export default class GameField {
|
||||||
constructor({ fieldArray = [], fieldMap = {} }) {
|
constructor({ fieldArray = [], fieldMap = {} }) {
|
||||||
|
@ -7,12 +7,12 @@ export default class GameField {
|
||||||
fieldArray.forEach((subArray, majorIndex) =>
|
fieldArray.forEach((subArray, majorIndex) =>
|
||||||
subArray.forEach((value, minorIndex) => {
|
subArray.forEach((value, minorIndex) => {
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
this.map[`${majorIndex}-${minorIndex}`] = new Cell(true);
|
this.map[`${majorIndex}-${minorIndex}`] = cellStream(true, 0);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
for (let key in fieldMap) {
|
for (let key in fieldMap) {
|
||||||
this.map[key] = new Cell(true);
|
this.map[key] = cellStream(true, 0);
|
||||||
}
|
}
|
||||||
// instead of implementing multiple GameFields, clear irrelevant keys and expand Game Field as needed
|
// instead of implementing multiple GameFields, clear irrelevant keys and expand Game Field as needed
|
||||||
// discrete Field expansion should only happen in View (to keep view fields centered)
|
// discrete Field expansion should only happen in View (to keep view fields centered)
|
||||||
|
@ -20,3 +20,7 @@ export default class GameField {
|
||||||
}
|
}
|
||||||
|
|
||||||
// as a stream -> fieldStream => Stream(GameField, () => Stream(fieldStream.computeNeighbors(), () => Stream(fieldStream.setLiving()))
|
// as a stream -> fieldStream => Stream(GameField, () => Stream(fieldStream.computeNeighbors(), () => Stream(fieldStream.setLiving()))
|
||||||
|
|
||||||
|
// instantiate table (orientation of major and minor axis dependent on viewport)
|
||||||
|
// const gameFields = new Array(1).fill(new GameField({}));
|
||||||
|
// const container = document.getElementById("game-field");
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import css from "./styles/reset.css";
|
import reset from "./styles/reset.css";
|
||||||
require("./components/Cell")(() => console.log("hello world!"))();
|
import css from "./styles/style.css";
|
||||||
|
// import Controls from './components/Controls';
|
||||||
|
import GameField from "./components/GameField";
|
||||||
|
(() => console.log("hello world!"))();
|
||||||
|
|
||||||
// controls
|
// controls
|
||||||
// -- state=idle ?
|
// -- state=idle ?
|
||||||
|
|
19
src/styles/style.css
Normal file
19
src/styles/style.css
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
* {
|
||||||
|
background: #333;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main, aside {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import Cell from "../components/Cell";
|
import { Cell, cellStream } from "../components/Cell";
|
||||||
|
|
||||||
describe("Cell functionality", () => {
|
describe("Cell functionality", () => {
|
||||||
test("dispatch toggleLiving state should mark living cell dead", () => {
|
test("dispatch toggleLiving state should mark living cell dead", () => {
|
||||||
|
@ -42,4 +42,27 @@ describe("Cell functionality", () => {
|
||||||
expect(cell.living).toEqual(state);
|
expect(cell.living).toEqual(state);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const cellStreamNextCalls = [
|
||||||
|
[2, false],
|
||||||
|
[3, true],
|
||||||
|
[0, false],
|
||||||
|
[5, false],
|
||||||
|
];
|
||||||
|
|
||||||
|
cellStreamNextCalls.forEach(([liveNeighbors, livingResult]) => {
|
||||||
|
test(`cellStream advances cell state for ${liveNeighbors} live Neighbors (from dead cell)`, () => {
|
||||||
|
const cell = cellStream(false, liveNeighbors).next;
|
||||||
|
expect(cell.living).toEqual(livingResult);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[[2, true], ...cellStreamNextCalls.slice(1)].forEach(
|
||||||
|
([liveNeighbors, livingResult]) => {
|
||||||
|
test(`cellStream advances cell state for ${liveNeighbors} live Neighbors (from living cell)`, () => {
|
||||||
|
const cell = cellStream(true, liveNeighbors).next;
|
||||||
|
expect(cell.living).toEqual(livingResult);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
import GameField from "../components/GameField";
|
import GameField from "../components/GameField";
|
||||||
|
|
||||||
describe("Game Field", () => {
|
|
||||||
test("smoke test", () => {
|
|
||||||
expect(new GameField([])).toEqual({ map: {} });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Game Field seeds living Cells with array", () => {
|
describe("Game Field seeds living Cells with array", () => {
|
||||||
const gameArraySeed = new GameField({
|
const gameArraySeed = new GameField({
|
||||||
fieldArray: [
|
fieldArray: [
|
||||||
|
|
Loading…
Reference in a new issue