@afshin/life
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -1,100 +0,92 @@ | ||
import { Widget } from '@phosphor/widgets'; | ||
import { DataGrid, DataModel } from '@phosphor/datagrid'; | ||
import '../style/index.css'; | ||
/** | ||
* A class that renders a UI for Conway's Game of Life. | ||
*/ | ||
export declare class LifeWidget extends Widget { | ||
export declare namespace Life { | ||
interface IStyle { | ||
alive?: string; | ||
empty?: string; | ||
size?: number; | ||
} | ||
class Model extends DataModel { | ||
constructor(options?: Model.IOptions); | ||
/** | ||
* The current state of the universe. | ||
*/ | ||
state: Model.Bit[][]; | ||
rowCount(region: DataModel.RowRegion): number; | ||
columnCount(region: DataModel.ColumnRegion): number; | ||
data(region: DataModel.CellRegion, row: number, column: number): any; | ||
/** | ||
* Start ticking the life widget, rendering each generation. | ||
*/ | ||
start(): void; | ||
/** | ||
* Stop ticking the life widget. | ||
*/ | ||
stop(): void; | ||
private _interval; | ||
private _data; | ||
private _swap; | ||
private _started; | ||
private _tick; | ||
} | ||
/** | ||
* Create a Game of Life widget. | ||
* A namespace for `Model` statics. | ||
*/ | ||
constructor(options?: LifeWidget.IOptions); | ||
/** | ||
* The current state of the universe. | ||
*/ | ||
state: LifeWidget.Bit[][]; | ||
/** | ||
* Start ticking the life widget, rendering each generation. | ||
*/ | ||
start(): void; | ||
/** | ||
* Stop ticking the life widget. | ||
*/ | ||
stop(): void; | ||
/** | ||
* Handle `before-detach` messages. | ||
*/ | ||
protected onBeforeDetach(): void; | ||
/** | ||
* Handle `update-request` messages. | ||
*/ | ||
protected onUpdateRequest(): void; | ||
/** | ||
* Render the DOM nodes for a life widget. | ||
*/ | ||
private _render(); | ||
private _interval; | ||
private _next; | ||
private _prev; | ||
private _rows; | ||
private _started; | ||
private _tick; | ||
} | ||
/** | ||
* A namespace for `LifeWidget` statics. | ||
*/ | ||
export declare namespace LifeWidget { | ||
/** | ||
* The basic unit of life, `1` represents life. | ||
*/ | ||
type Bit = 1 | 0; | ||
/** | ||
* The tick function type for calculating new generations of life. | ||
*/ | ||
type Tick = (prev: Bit[][], next: Bit[][], fluctuation?: number) => void; | ||
/** | ||
* The instantiation options for a life widget. | ||
*/ | ||
interface IOptions { | ||
namespace Model { | ||
/** | ||
* The initial state of the universe, defaults to a random world. | ||
* The basic unit of life, `1` represents life. | ||
*/ | ||
initial?: Bit[][]; | ||
type Bit = 1 | 0; | ||
/** | ||
* The time (in ms) between generations and rendering, defaults to `250`. | ||
* The tick function type for calculating new generations of life. | ||
*/ | ||
interval?: number; | ||
type Tick = (prev: Bit[][], next: Bit[][], fluctuation?: number) => void; | ||
/** | ||
* A function used to calculate generations, defaults to `LifeWidget.tick`. | ||
* The instantiation options for a life widget. | ||
*/ | ||
tick?: Tick; | ||
interface IOptions { | ||
/** | ||
* The initial state of the universe, defaults to a random world. | ||
*/ | ||
initial?: Bit[][]; | ||
/** | ||
* The time (in ms) between generations and rendering, defaults to `250`. | ||
*/ | ||
interval?: number; | ||
/** | ||
* A function used to calculate generations, defaults to `LifeWidget.tick`. | ||
*/ | ||
tick?: Tick; | ||
} | ||
/** | ||
* Generates a random data set to initialize the state of the world. | ||
* | ||
* @param rows - The number of rows in the data, defaults to `40`. | ||
* | ||
* @param columns - The number of columns in the data, defaults to `40`. | ||
* | ||
* @param likelihood - The likelihood of a live cell, defaults to `0.25`. | ||
* | ||
* @returns A two-dimensional array representing the state of the world. | ||
*/ | ||
function random(rows?: number, columns?: number, likelihood?: number): Bit[][]; | ||
/** | ||
* Process a generation of life following Conway's original rules. | ||
* | ||
* @param input - The current state of the world. | ||
* | ||
* @param output - An array that will be populated with the next generation. | ||
* | ||
* @param fluctuation - An optional value between 0 and 1 that indicates the | ||
* likelihood that a bit will flip, contravening the rules. | ||
* | ||
* #### Notes | ||
* Instead of accepting a single state array, this function takes an `input` | ||
* and an `output` array to faciliate swapping back and forth between | ||
* generation arrays without needing to reallocate memory. The `input` and | ||
* `output` arrays must have the same dimensions. | ||
*/ | ||
function tick(input: Bit[][], output: Bit[][], fluctuation?: number): void; | ||
} | ||
/** | ||
* Generates a random data set to initialize the state of the world. | ||
* | ||
* @param rows - The number of rows in the data, defaults to `40`. | ||
* | ||
* @param columns - The number of columns in the data, defaults to `40`. | ||
* | ||
* @param likelihood - The likelihood of a live cell, defaults to `0.25`. | ||
* | ||
* @returns A two-dimensional array representing the state of the world. | ||
*/ | ||
function random(rows?: number, columns?: number, likelihood?: number): LifeWidget.Bit[][]; | ||
/** | ||
* Process a generation of life following Conway's original rules. | ||
* | ||
* @param input - The current state of the world. | ||
* | ||
* @param output - An array that will be populated with the next generation. | ||
* | ||
* @param fluctuation - An optional value between 0 and 1 that indicates the | ||
* likelihood that a bit will flip, contravening the rules. | ||
* | ||
* #### Notes | ||
* Instead of accepting a single state array, this function takes an `input` | ||
* and an `output` array to faciliate swapping back and forth between | ||
* generation arrays without needing to reallocate memory. The `input` and | ||
* `output` arrays must have the same dimensions. | ||
*/ | ||
function tick(input: Bit[][], output: Bit[][], fluctuation?: number): void; | ||
function create(model: Model, style?: IStyle): DataGrid; | ||
} |
418
lib/index.js
@@ -12,4 +12,12 @@ "use strict"; | ||
})(); | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var widgets_1 = require("@phosphor/widgets"); | ||
var datagrid_1 = require("@phosphor/datagrid"); | ||
require("../style/index.css"); | ||
@@ -32,245 +40,195 @@ /** | ||
var INTERVAL = 250; | ||
/** | ||
* A class that renders a UI for Conway's Game of Life. | ||
*/ | ||
var LifeWidget = /** @class */ (function (_super) { | ||
__extends(LifeWidget, _super); | ||
/** | ||
* Create a Game of Life widget. | ||
*/ | ||
function LifeWidget(options) { | ||
if (options === void 0) { options = {}; } | ||
var _this = _super.call(this) || this; | ||
// Populate the initial state. | ||
_this.state = options.initial || LifeWidget.random(); | ||
_this._interval = options.interval || INTERVAL; | ||
_this._tick = options.tick || LifeWidget.tick; | ||
_this.addClass('ad-LifeWidget'); | ||
return _this; | ||
} | ||
Object.defineProperty(LifeWidget.prototype, "state", { | ||
var Life; | ||
(function (Life) { | ||
var Model = /** @class */ (function (_super) { | ||
__extends(Model, _super); | ||
function Model(options) { | ||
if (options === void 0) { options = {}; } | ||
var _this = _super.call(this) || this; | ||
_this._interval = options.interval || INTERVAL; | ||
_this._tick = options.tick || Model.tick; | ||
_this.state = options.initial || Model.random(); | ||
return _this; | ||
} | ||
Object.defineProperty(Model.prototype, "state", { | ||
/** | ||
* The current state of the universe. | ||
*/ | ||
get: function () { | ||
return this._data; | ||
}, | ||
set: function (state) { | ||
if (this._started) { | ||
this.stop(); | ||
} | ||
this._data = state; | ||
this._swap = JSON.parse(JSON.stringify(state)); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Model.prototype.rowCount = function (region) { | ||
return this._data.length; | ||
}; | ||
Model.prototype.columnCount = function (region) { | ||
return this._data[0].length; | ||
}; | ||
Model.prototype.data = function (region, row, column) { | ||
return this._data[row][column]; | ||
}; | ||
/** | ||
* The current state of the universe. | ||
* Start ticking the life widget, rendering each generation. | ||
*/ | ||
get: function () { | ||
return this._next; | ||
}, | ||
set: function (state) { | ||
Model.prototype.start = function () { | ||
var _this = this; | ||
var swap = false; | ||
if (this._started) { | ||
this.stop(); | ||
} | ||
// Populate the data. | ||
this._prev = state; | ||
this._next = JSON.parse(JSON.stringify(state)); | ||
// Populate the node. | ||
this._render(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Start ticking the life widget, rendering each generation. | ||
*/ | ||
LifeWidget.prototype.start = function () { | ||
var _this = this; | ||
var swap = false; | ||
if (this._started) { | ||
this.stop(); | ||
} | ||
this._started = window.setInterval(function () { | ||
if (!_this.isAttached) { | ||
return; | ||
this._started = window.setInterval(function () { | ||
// Use a pointer to swap lists back so their names make semantic sense. | ||
if (swap = !swap) { | ||
var swapped = _this._data; | ||
_this._data = _this._swap; | ||
_this._swap = swapped; | ||
} | ||
_this._tick(_this._swap, _this._data); | ||
_this.emitChanged({ | ||
type: 'cells-changed', | ||
rowSpan: _this._data.length, | ||
columnSpan: _this._data[0].length, | ||
region: 'body', | ||
rowIndex: 0, | ||
columnIndex: 0 | ||
}); | ||
}, this._interval); | ||
}; | ||
/** | ||
* Stop ticking the life widget. | ||
*/ | ||
Model.prototype.stop = function () { | ||
if (this._started) { | ||
window.clearInterval(this._started); | ||
this._started = 0; | ||
} | ||
// Use a pointer to swap lists back so their names make semantic sense. | ||
if (swap = !swap) { | ||
var prev = _this._next; | ||
_this._next = _this._prev; | ||
_this._prev = prev; | ||
} | ||
// Calculate the new state. | ||
_this._tick(_this._prev, _this._next); | ||
// Update the UI. | ||
_this.update(); | ||
}, this._interval); | ||
}; | ||
}; | ||
return Model; | ||
}(datagrid_1.DataModel)); | ||
Life.Model = Model; | ||
/** | ||
* Stop ticking the life widget. | ||
* A namespace for `Model` statics. | ||
*/ | ||
LifeWidget.prototype.stop = function () { | ||
if (this._started) { | ||
window.clearInterval(this._started); | ||
this._started = 0; | ||
} | ||
}; | ||
/** | ||
* Handle `before-detach` messages. | ||
*/ | ||
LifeWidget.prototype.onBeforeDetach = function () { | ||
this.stop(); | ||
}; | ||
/** | ||
* Handle `update-request` messages. | ||
*/ | ||
LifeWidget.prototype.onUpdateRequest = function () { | ||
var next = this._next; | ||
var prev = this._prev; | ||
var rows = next.length; | ||
var columns = next[0].length; | ||
for (var i = 0; i < rows; i += 1) { | ||
for (var j = 0; j < columns; j += 1) { | ||
var current = next[i][j]; | ||
var list = this._rows[i]; | ||
if (prev[i][j] !== current) { | ||
list[j].className = current ? 'ad-mod-alive' : ''; | ||
(function (Model) { | ||
/** | ||
* Generates a random data set to initialize the state of the world. | ||
* | ||
* @param rows - The number of rows in the data, defaults to `40`. | ||
* | ||
* @param columns - The number of columns in the data, defaults to `40`. | ||
* | ||
* @param likelihood - The likelihood of a live cell, defaults to `0.25`. | ||
* | ||
* @returns A two-dimensional array representing the state of the world. | ||
*/ | ||
function random(rows, columns, likelihood) { | ||
if (rows === void 0) { rows = ROWS; } | ||
if (columns === void 0) { columns = COLUMNS; } | ||
if (likelihood === void 0) { likelihood = LIKELIHOOD; } | ||
var data = []; | ||
for (var i = 0; i < rows; i += 1) { | ||
var row = []; | ||
data.push(row); | ||
for (var j = 0; j < columns; j += 1) { | ||
row[j] = Math.random() < likelihood ? 1 : 0; | ||
} | ||
} | ||
return data; | ||
} | ||
}; | ||
/** | ||
* Render the DOM nodes for a life widget. | ||
*/ | ||
LifeWidget.prototype._render = function () { | ||
var _a = this, node = _a.node, state = _a.state; | ||
// Empty the node and populate its HTML. | ||
node.textContent = ''; | ||
node.appendChild(Private.createTable(state)); | ||
// Populate a cached handle to each row and cell. | ||
var rows = node.querySelectorAll('.ad-LifeWidget-row'); | ||
this._rows = []; | ||
for (var i = 0; i < rows.length; i += 1) { | ||
this._rows.push(rows[i].querySelectorAll('div')); | ||
} | ||
}; | ||
return LifeWidget; | ||
}(widgets_1.Widget)); | ||
exports.LifeWidget = LifeWidget; | ||
/** | ||
* A namespace for `LifeWidget` statics. | ||
*/ | ||
(function (LifeWidget) { | ||
/** | ||
* Generates a random data set to initialize the state of the world. | ||
* | ||
* @param rows - The number of rows in the data, defaults to `40`. | ||
* | ||
* @param columns - The number of columns in the data, defaults to `40`. | ||
* | ||
* @param likelihood - The likelihood of a live cell, defaults to `0.25`. | ||
* | ||
* @returns A two-dimensional array representing the state of the world. | ||
*/ | ||
function random(rows, columns, likelihood) { | ||
if (rows === void 0) { rows = ROWS; } | ||
if (columns === void 0) { columns = COLUMNS; } | ||
if (likelihood === void 0) { likelihood = LIKELIHOOD; } | ||
var data = []; | ||
for (var i = 0; i < rows; i += 1) { | ||
var row = []; | ||
data.push(row); | ||
for (var j = 0; j < columns; j += 1) { | ||
row[j] = Math.random() < likelihood ? 1 : 0; | ||
} | ||
} | ||
return data; | ||
} | ||
LifeWidget.random = random; | ||
/** | ||
* Process a generation of life following Conway's original rules. | ||
* | ||
* @param input - The current state of the world. | ||
* | ||
* @param output - An array that will be populated with the next generation. | ||
* | ||
* @param fluctuation - An optional value between 0 and 1 that indicates the | ||
* likelihood that a bit will flip, contravening the rules. | ||
* | ||
* #### Notes | ||
* Instead of accepting a single state array, this function takes an `input` | ||
* and an `output` array to faciliate swapping back and forth between | ||
* generation arrays without needing to reallocate memory. The `input` and | ||
* `output` arrays must have the same dimensions. | ||
*/ | ||
function tick(input, output, fluctuation) { | ||
if (fluctuation === void 0) { fluctuation = 0; } | ||
var rows = input.length; | ||
var columns = input[0].length; | ||
var lastCol = columns - 1; | ||
var lastRow = rows - 1; | ||
for (var i = 0; i < rows; i += 1) { | ||
for (var j = 0; j < columns; j += 1) { | ||
var alive = input[i][j]; | ||
var cell = 0; | ||
var decX = i >= 1 ? i - 1 : lastRow; // decrement x | ||
var decY = j >= 1 ? j - 1 : lastCol; // decrement y | ||
var incX = i + 1 <= lastRow ? i + 1 : 0; // increment x | ||
var incY = j + 1 <= lastCol ? j + 1 : 0; // increment y | ||
var neighbors = input[decX][decY] + | ||
input[i][decY] + | ||
input[incX][decY] + | ||
input[decX][j] + | ||
input[incX][j] + | ||
input[decX][incY] + | ||
input[i][incY] + | ||
input[incX][incY]; | ||
// Any live cell with fewer than two live neighbors dies. | ||
// Any live cell with two or three live neighbors lives. | ||
// Any live cell with more than three live neighbors dies. | ||
// Any dead cell with exactly three live neighbors becomes a live cell. | ||
if (alive && neighbors < 2) { | ||
cell = 0; | ||
Model.random = random; | ||
/** | ||
* Process a generation of life following Conway's original rules. | ||
* | ||
* @param input - The current state of the world. | ||
* | ||
* @param output - An array that will be populated with the next generation. | ||
* | ||
* @param fluctuation - An optional value between 0 and 1 that indicates the | ||
* likelihood that a bit will flip, contravening the rules. | ||
* | ||
* #### Notes | ||
* Instead of accepting a single state array, this function takes an `input` | ||
* and an `output` array to faciliate swapping back and forth between | ||
* generation arrays without needing to reallocate memory. The `input` and | ||
* `output` arrays must have the same dimensions. | ||
*/ | ||
function tick(input, output, fluctuation) { | ||
if (fluctuation === void 0) { fluctuation = 0; } | ||
var rows = input.length; | ||
var columns = input[0].length; | ||
var lastCol = columns - 1; | ||
var lastRow = rows - 1; | ||
for (var i = 0; i < rows; i += 1) { | ||
for (var j = 0; j < columns; j += 1) { | ||
var alive = input[i][j]; | ||
var cell = 0; | ||
var decX = i >= 1 ? i - 1 : lastRow; // decrement x | ||
var decY = j >= 1 ? j - 1 : lastCol; // decrement y | ||
var incX = i + 1 <= lastRow ? i + 1 : 0; // increment x | ||
var incY = j + 1 <= lastCol ? j + 1 : 0; // increment y | ||
var neighbors = input[decX][decY] + | ||
input[i][decY] + | ||
input[incX][decY] + | ||
input[decX][j] + | ||
input[incX][j] + | ||
input[decX][incY] + | ||
input[i][incY] + | ||
input[incX][incY]; | ||
// Any live cell with fewer than two live neighbors dies. | ||
// Any live cell with two or three live neighbors lives. | ||
// Any live cell with more than three live neighbors dies. | ||
// Any dead cell with exactly three live neighbors becomes a live cell. | ||
if (alive && neighbors < 2) { | ||
cell = 0; | ||
} | ||
else if (alive && neighbors === 2 || neighbors === 3) { | ||
cell = 1; | ||
} | ||
else if (alive && neighbors > 3) { | ||
cell = 0; | ||
} | ||
else if (!alive && neighbors === 3) { | ||
cell = 1; | ||
} | ||
// If there is a fluctuation, flip the cell value. | ||
if (fluctuation && Math.random() < fluctuation) { | ||
cell = 1 - cell; | ||
} | ||
output[i][j] = cell; // Record the tick value. | ||
} | ||
else if (alive && neighbors === 2 || neighbors === 3) { | ||
cell = 1; | ||
} | ||
else if (alive && neighbors > 3) { | ||
cell = 0; | ||
} | ||
else if (!alive && neighbors === 3) { | ||
cell = 1; | ||
} | ||
// If there is a fluctuation, flip the cell value. | ||
if (fluctuation && Math.random() < fluctuation) { | ||
cell = 1 - cell; | ||
} | ||
output[i][j] = cell; // Record the tick value. | ||
} | ||
} | ||
Model.tick = tick; | ||
})(Model = Life.Model || (Life.Model = {})); | ||
function create(model, style) { | ||
if (style === void 0) { style = {}; } | ||
var grid = new datagrid_1.DataGrid({ | ||
baseColumnSize: style.size || 9, | ||
baseRowSize: style.size || 9, | ||
headerVisibility: 'none', | ||
style: __assign({}, datagrid_1.DataGrid.defaultStyle, { gridLineColor: "rgba(255, 255, 255, 0.5)", voidColor: 'transparent' }) | ||
}); | ||
var renderer = new datagrid_1.TextRenderer({ | ||
backgroundColor: function (_a) { | ||
var value = _a.value; | ||
return value === 1 ? style.alive || "rgb(0, 0, 0)" | ||
: style.empty || "rgb(50, 185, 25)"; | ||
}, | ||
format: function () { return ''; } | ||
}); | ||
grid.model = model; | ||
grid.addClass('ad-Life'); | ||
grid.cellRenderers.set('body', {}, renderer); | ||
return grid; | ||
} | ||
LifeWidget.tick = tick; | ||
})(LifeWidget = exports.LifeWidget || (exports.LifeWidget = {})); | ||
exports.LifeWidget = LifeWidget; | ||
/** | ||
* A namespace for private module data. | ||
*/ | ||
var Private; | ||
(function (Private) { | ||
/** | ||
* Create a row in the world. | ||
*/ | ||
function createRow(cells) { | ||
var row = document.createElement('div'); | ||
var columns = cells.length; | ||
// Populate columns. | ||
for (var i = 0; i < columns; i += 1) { | ||
var cell = document.createElement('div'); | ||
cell.className = cells[i] ? 'ad-mod-alive' : ''; | ||
row.appendChild(cell); | ||
} | ||
row.className = 'ad-LifeWidget-row'; | ||
return row; | ||
} | ||
Private.createRow = createRow; | ||
/** | ||
* Create the DOM nodes representing the world. | ||
*/ | ||
function createTable(data) { | ||
var fragment = document.createDocumentFragment(); | ||
var rows = data.length; | ||
// Populate rows. | ||
for (var i = 0; i < rows; i += 1) { | ||
fragment.appendChild(createRow(data[i])); | ||
} | ||
return fragment; | ||
} | ||
Private.createTable = createTable; | ||
})(Private || (Private = {})); | ||
Life.create = create; | ||
})(Life = exports.Life || (exports.Life = {})); |
{ | ||
"name": "@afshin/life", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "An implementation of Conway's Game of Life", | ||
@@ -32,4 +32,5 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@phosphor/datagrid": "^0.1.5", | ||
"@phosphor/widgets": "^1.5.0" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14673
2
333
+ Added@phosphor/datagrid@^0.1.5
+ Added@phosphor/datagrid@0.1.11(transitive)