stub out stream for Cell

This commit is contained in:
Sorrel Bri 2020-05-24 12:48:31 -07:00
parent f46b72f6db
commit 530acc0aeb
6 changed files with 96 additions and 13 deletions

View file

@ -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,
};

View file

@ -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");

View file

@ -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
View 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%;
}

View file

@ -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);
});
}
);
}); });

View file

@ -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: [