Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@afshin/life

Package Overview
Dependencies
Maintainers
2
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@afshin/life - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

170

lib/index.d.ts

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc