flocc 0.5.18 → 0.5.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,41 +8,105 @@ declare interface RuleObj {
8
8
  args: Array<any>;
9
9
  }
10
10
  /**
11
+ * This class puts the `Agent` in 'agent-based modeling.' More specifically,
12
+ * an `Agent` represents an individual unit of data and its associated
13
+ * behaviors.
11
14
  * @since 0.0.5
12
15
  */
13
16
  declare class Agent implements DataObj {
14
17
  /**
15
- * @member {Environment|null} environment
16
- * @member {RuleObj[]} rules
17
- * @member {RuleObj[]} queue
18
- * @member {Object} data
18
+ * An `Agent` can only belong to a single {@linkcode Environment}. When
19
+ * `environment.addAgent(agent);` is called, this is value is updated
20
+ * to point to that `Environment`.
21
+ *
22
+ * ```js
23
+ * const environment = new Environment();
24
+ * const agent = new Agent();
25
+ * agent.environment; // returns `null`
26
+ *
27
+ * environment.addAgent(agent);
28
+ * agent.environment === environment; // returns `true`
19
29
  */
20
30
  environment: Environment;
31
+ /** @hidden */
21
32
  rules: Array<RuleObj>;
33
+ /** @hidden */
22
34
  queue: Array<RuleObj>;
35
+ /** @hidden */
23
36
  data: Data;
37
+ /**
38
+ * `Agent`s are automatically assigned a unique ID when they are created.
39
+ * This can be useful when you need to refer to a specific `Agent`, and
40
+ * they can be retrieved using their ID from their `Environment` by calling
41
+ * {@link Environment.getAgentById | `environment.getAgentById(id);`}
42
+ * ```js
43
+ * const agent = new Agent();
44
+ * const id = agent.id; // returns "59B4F928-46C8-..." (for example)
45
+ * ```
46
+ */
24
47
  id: string;
48
+ /**
49
+ * This is used as a temporary store for data that
50
+ * gets returned from rules. When enqueued rules are executed,
51
+ * even if there aren't any enqueued rules, .set gets called
52
+ * on any data that was placed here.
53
+ * @hidden
54
+ */
25
55
  __newData: Data;
56
+ /** When agent.get('key') is called, this pseudo-private member is set to 'key'.
57
+ * Once it is retrieved, it is reset to null. If agent.get('key') is called before
58
+ * this has been reset, that means that there is an infinite loop, and the call
59
+ * will throw an error.
60
+ * @hidden
61
+ */
26
62
  __retrievingData: string;
63
+ /** @hidden */
27
64
  __subtree: KDTree;
65
+ /**
66
+ * `Agent`s can be instantiated with or without data. Instantiating
67
+ * with data is equivalent to creating an `Agent` and immediately
68
+ * calling {@linkcode Agent.set} to add data.
69
+ *
70
+ * ```js
71
+ * // instantiates an Agent without data
72
+ * const a = new Agent();
73
+ *
74
+ * // instantiates an Agent with data
75
+ * const b = new Agent({
76
+ * x: 50,
77
+ * y: 100
78
+ * });
79
+ * ```
80
+ * @param data
81
+ */
28
82
  constructor(data?: Data);
29
83
  /**
30
84
  * Set a function value. `tick` and `queue` are not automatically called,
31
85
  * but any other named value will automatically be called when referenced.
32
- * @param {string} name
33
- * @param {Function} fn
86
+ * @hidden
34
87
  */
35
88
  _setFunctionValue(name: string, fn: Function): void;
36
89
  /**
37
- * Retrieve an arbitrary piece of data associated
38
- * with this agent by name.
39
- * @param {string} name
90
+ * Retrieve an arbitrary piece of data associated by name.
91
+ * If the data has not been {@linkcode set}, returns `null`.
40
92
  * @since 0.0.5
41
93
  */
42
94
  get(name: string): any;
43
95
  /**
44
- * Retrieve all the data associated with this agent
45
- * (useful for destructuring properties).
96
+ * Retrieve all the data associated with this `Agent` at once.
97
+ *
98
+ * ```js
99
+ * agent.set('x', 3);
100
+ * agent.set('color', 'blue');
101
+ * agent.set('active', false);
102
+ *
103
+ * agent.getData();
104
+ * // returns {
105
+ * // x: 3,
106
+ * // color: 'blue',
107
+ * // active: false
108
+ * // }
109
+ * ```
46
110
  * @since 0.1.0
47
111
  */
48
112
  getData(): Data;
@@ -60,60 +124,133 @@ declare class Agent implements DataObj {
60
124
  /**
61
125
  * Helper function to set key-value pair depending on whether value
62
126
  * is a function (callable) or not
127
+ * @hidden
63
128
  */
64
129
  _setKeyValue(key: string, value: any): void;
65
130
  /**
66
- * Increment a numeric (assume integer) piece of data
67
- * associated with this agent. If `n` is included, increments by
68
- * `n`. If the value has not yet been set, initializes it to 1.
69
- * @param {string} name
70
- * @param {number} n
131
+ * increment a numeric piece of data associated with this `Agent`
132
+ * (increasing its value by 1). This method is *synchronous* &mdash;
133
+ * it immediately increases the value (to *asynchronously* increase it,
134
+ * the rule function should instead return a new value.
135
+ *
136
+ * ```js
137
+ * agent.set('x', 50);
138
+ * agent.increment('x');
139
+ * agent.get('x'); // returns 51
140
+ * ```
141
+ *
142
+ * If the second parameter `n` is included, decrements by that amount.
143
+ *
144
+ * ```js
145
+ * agent.set('x', 50);
146
+ * agent.increment('x', 10);
147
+ * agent.get('x'); // returns 60
148
+ * ```
149
+ *
150
+ * If the value has not yet been set, calling this method sets it to `1`
151
+ * (or to `n`).
71
152
  * @since 0.0.8
72
153
  */
73
154
  increment(name: string, n?: number): void;
74
155
  /**
75
- * Decrement a numeric (assume integer) piece of data
76
- * associated with this agent. If `n` is included, decrements by
77
- * `n`. If the value has not yet been set,
78
- * initializes it to -1.
79
- * @param {string} name
156
+ * Decrement a numeric piece of data associated with this `Agent`
157
+ * (decreasing its value by 1). This method is *synchronous* &mdash;
158
+ * it immediately decreases the value (to *asynchronously* decrease it,
159
+ * the rule function should instead return a new value.
160
+ *
161
+ * ```js
162
+ * agent.set('x', 50);
163
+ * agent.decrement('x');
164
+ * agent.get('x'); // returns 49
165
+ * ```
166
+ *
167
+ * If the second parameter `n` is included, decrements by that amount.
168
+ *
169
+ * ```js
170
+ * agent.set('x', 50);
171
+ * agent.decrement('x', 10);
172
+ * agent.get('x'); // returns 40
173
+ * ```
174
+ *
175
+ * If the value has not yet been set, calling this method sets it to `-1`
176
+ * (or to `-n`).
80
177
  * @since 0.0.8
81
178
  */
82
179
  decrement(name: string, n?: number): void;
83
180
  /**
84
- * Add a rule to be executed during the agent's
85
- * environment's tick cycle. When executed, the
86
- * @param {Function | Rule} rule
181
+ * Until v0.5.14, this was the preferred way to add behavior to `Agent`s.
182
+ * Now, the preferred method is by setting the `Agent`'s `"tick"` value (i.e. `agent.set({ tick: function(agt) { ... }})`).
183
+ * This method will still be allowed until v0.7.0.
184
+ *
185
+ * Adds a rule (a function taking an `Agent` as a callback or a {@linkcode Rule} object) that may be run with every {@linkcode Environment.tick}.
186
+ * It is possible to add *more than one rule* to an `Agent`, although it
187
+ * is generally easier to write a longer function or to break it apart
188
+ * into multiple functions.
189
+ *
190
+ * ```js
191
+ * // adds a rule that *synchronously* increments the Agent's "x" value
192
+ * agent.addRule(function(agt) {
193
+ * agent.increment('x');
194
+ * });
195
+ *
196
+ * // adds a rule that *asynchronously* increments the Agent's "x" value
197
+ * agent.addRule(function(agt) {
198
+ * return {
199
+ * x: agt.get('x') + 1
200
+ * };
201
+ * });
202
+ * ```
203
+ *
87
204
  * @deprecated since version 0.5.14
88
205
  * @since 0.0.5
89
206
  */
90
207
  addRule(rule: Function | Rule, ...args: Array<any>): void;
91
208
  /**
92
- * Enqueue a function to be executed at the end of
93
- * the agent's environment's tick cycle (for example,
94
- * if agents in an environment should perform their
95
- * calculations and updates separately). Additional/external
96
- * data passed in as arguments to the enqueued function will
209
+ * Like {@linkcode Agent.addRule}, this method is deprecated and the
210
+ * recommended way is to now call
211
+ * `agent.set('queue', function(agt) { ... });`
212
+ *
213
+ * Calling this method enqueues a function to be executed
214
+ * *asynchronously* (at the end of the {@linkcode Environment}'s tick cycle).
215
+ * This is useful if a 'cleanup pass' should be performed between
216
+ * time steps to adjust `Agent` data.
217
+ *
218
+ * Below, the `Agent` sets its `"x"` value to `30` whenever it is
219
+ * activated during the `Environment`'s tick cycle. After all of that
220
+ * cycle's `Agent`s have been activated, this `Agent` sets its `"x"`
221
+ * value to `20`. So if any other `Agent` references its `"x"` value
222
+ * during a tick cycle after it has been activated, it will return `30`,
223
+ * but in between tick cycles it will return `20`.
224
+ *
225
+ * ```js
226
+ * agent.addRule(agt => {
227
+ * agt.set("x", 30);
228
+ * agt.enqueue(a => {
229
+ * a.set("x", 20);
230
+ * });
231
+ * });
232
+ * ```
233
+ *
234
+ * Any additional parameters passed to the enqueued function will
97
235
  * be remembered and passed through when the function is executed.
98
236
  *
99
- * The `queue` array is cleared at the very end of
100
- * the environment's tick cycle.
101
- * @param {Function} enqueuedRule
102
237
  * @deprecated since version 0.5.14
103
238
  * @since 0.0.5
104
239
  */
105
240
  enqueue(rule: Function, ...args: Array<any>): void;
106
241
  /**
107
242
  * From a RuleObj, execute a single rule (function or structured Rule).
108
- * @param {RuleObj} ruleObj
243
+ * @hidden
109
244
  */
110
245
  executeRule(ruleObj: RuleObj): Data;
111
246
  /**
112
247
  * Execute all rules.
248
+ * @hidden
113
249
  */
114
250
  executeRules(): void;
115
251
  /**
116
252
  * Execute all enqueued rules.
253
+ * @hidden
117
254
  */
118
255
  executeEnqueuedRules(): void;
119
256
  }
@@ -13,6 +13,7 @@ interface Helpers {
13
13
  }
14
14
  export interface TickOptions {
15
15
  activation?: "uniform" | "random";
16
+ activationCount?: number;
16
17
  count?: number;
17
18
  randomizeOrder?: boolean;
18
19
  }
@@ -23,33 +24,80 @@ interface MemoValue {
23
24
  time: number;
24
25
  }
25
26
  /**
26
- * An environment provides the space and time in which agents interact.
27
- * Environments, like agents, can store data in key-value pairs
28
- * that can be updated over time.
27
+ * An environment provides the space and time in which Agents interact.
28
+ * Environments are themselves Agents, and can store data in key-value
29
+ * pairs that can be manipulated just like Agent data.
29
30
  * @since 0.0.5
30
31
  */
31
32
  declare class Environment extends Agent {
32
- /** @member {Agent[]} */
33
+ /** @hidden */
33
34
  agents: Array<Agent>;
35
+ /** @hidden */
34
36
  agentsById: Map<string, Agent>;
37
+ /** @hidden */
38
+ environment: Environment;
39
+ /** @hidden */
35
40
  cache: Map<string, MemoValue>;
41
+ /** @hidden */
36
42
  helpers: Helpers;
37
- /** @member {AbstractRenderer[]} */
43
+ /** @hidden */
44
+ id: string;
45
+ /**
46
+ * An array of the renderers associated with this `Environment`.
47
+ * An `Environment` can have multiple renderers, usually one to render
48
+ * the {@linkcode Agent}s spatially and others for data visualization,
49
+ * such as a {@linkcode LineChartRenderer}, {@linkcode Histogram}, etc.
50
+ */
38
51
  renderers: AbstractRenderer[];
52
+ /** @hidden */
39
53
  opts: EnvironmentOptions;
40
54
  width: number;
41
55
  height: number;
42
- /** @since 0.1.4 */
56
+ /**
57
+ * This property will always equal the number of tick cycles that
58
+ * have passed since the `Environment` was created. If you call
59
+ * {@linkcode tick} so that it goes forward multiple time steps, it will
60
+ * increase the `time` by that value (not by just `1`, even though
61
+ * you only called `tick` once).
62
+ *
63
+ * ```js
64
+ * const environment = new Environment();
65
+ * environment.time; // returns 0
66
+ *
67
+ * environment.tick();
68
+ * environment.time; // returns 1
69
+ *
70
+ * environment.tick(3);
71
+ * environment.time; // returns 4
72
+ * ```
73
+ *
74
+ * @since 0.1.4
75
+ * */
43
76
  time: number;
77
+ /**
78
+ * Although `Environment`s inherit {@linkcode Agent} methods
79
+ * like {@linkcode Agent.set}, {@linkcode Agent.get}, etc. they have
80
+ * a different `constructor` signature.
81
+ *
82
+ * Pass in predefined `Environment` options for:
83
+ * - `torus` &mdash; Whether the `Environment` should wrap around in 2d space (with `Agent`s that move off the right reappearing on the left, off the top reappearing on the bottom, etc.)
84
+ * - `width` &mdash; The width of the `Environment` (used when `torus = true`)
85
+ * - `height` &mdash; The height of the `Environment` (used when `torus = true`)
86
+ * @override
87
+ */
44
88
  constructor(opts?: EnvironmentOptions);
45
89
  /**
46
- * Add an agent to the environment. Automatically sets the
47
- * agent's environment to be this environment.
48
- * @param {Agent} agent
49
- * @param {boolean} rebalance - Whether to rebalance if there is a KDTree (defaults to true)
90
+ * Add an {@linkcode Agent} to this `Environment`. Once this is called,
91
+ * the `Agent`'s {@link Agent.environment | `environment`} property
92
+ * will automatically be set to this `Environment`.
93
+ * @param rebalance - Whether to rebalance if there is a `KDTree` (defaults to true)
50
94
  * @since 0.0.5
51
95
  */
52
96
  addAgent(agent: Agent, rebalance?: boolean): void;
97
+ /** @hidden */
98
+ addRule: null;
99
+ /** @hidden */
100
+ enqueue: null;
53
101
  /**
54
102
  * Remove an agent from the environment.
55
103
  * @param {Agent} agent
@@ -77,57 +125,105 @@ declare class Environment extends Agent {
77
125
  */
78
126
  getAgentById(id: string): Agent | null;
79
127
  /**
80
- * Removes all agents from the environment.
128
+ * Remove all agents from the environment.
81
129
  * @since 0.1.3
82
130
  */
83
131
  clear(): void;
84
132
  /**
85
- * From the parameter passed to .tick, get a structured TickOptions object.
86
- * @param {number | TickOptions} opts
133
+ * From the parameter passed to {@linkcode Environment.tick}, get a structured TickOptions object.
134
+ * @hidden
87
135
  */
88
136
  _getTickOptions(opts?: number | TickOptions): TickOptions;
89
137
  /**
90
- * Execute all agent rules.
91
- * @param { boolean } randomizeOrder
138
+ * For all agents passed, execute agent rules
139
+ * @hidden
92
140
  */
93
- _executeAgentRules(randomizeOrder: boolean): void;
141
+ _executeAgentRules(agents: Agent[]): void;
94
142
  /**
95
- * Execute all enqueued agent rules.
96
- * @param { boolean } randomizeOrder
143
+ * For all agents passed, execute enqueued agent rules
144
+ * @hidden
97
145
  */
98
- _executeEnqueuedAgentRules(randomizeOrder: boolean): void;
99
- /**
100
- * Moves the environment forward in time,
101
- * executing all agent's rules sequentially, followed by
102
- * any enqueued rules (which are removed with every tick).
103
- * Can take either a number or a configuration object as a parameter.
104
- * If a number, the environment will tick forward that many times.
105
- * @param {number | TickOptions} opts
146
+ _executeEnqueuedAgentRules(agents: Agent[]): void;
147
+ /**
148
+ * Runs the `Environment`s tick cycle. Depending on the parameters, one,
149
+ * some, or all of the {@linkcode Agent}s in the `Environment`
150
+ * might be activated, and all renderers associated with the
151
+ * `Environment` will update. After the tick cycle finishes, any rules that were enqueued will be run and the `Environment`'s {@linkcode time} property will have incremented.
152
+ *
153
+ * ```js
154
+ * environment.tick(); // ticks once
155
+ *
156
+ * // To run multiple tick cycles, you can pass a number
157
+ * environment.tick(5); // ticks 5 times
158
+ * ```
159
+ *
160
+ * Passing a configuration object (instead of a number) allows
161
+ * you to have finer control over the tick cycle. The object can
162
+ * have the following keys:
163
+ * - `activation`: Either `"uniform"` or `"random"` (defaults to `"uniform"`).
164
+ * - `activation = "uniform"` &mdash; All `Agent`s in the `Environment` are activated with every tick cycle.
165
+ * - `activation = "random"` &mdash; One or more `Agent`s are randomly selected to be activated every tick cycle (see `activationCount` below).
166
+ * - `activationCount`: For `"random"` activation, this many `Agent`s will be activated with each tick cycle. Defaults to `1`. If `activationCount` is greater than the number of `Agent`s in the `Environment`, then all the `Agent`s will be activated exactly once in random order.
167
+ * - `count`: The number of tick cycles to run.
168
+ * - `randomizeOrder`: When `activation = "uniform"`, if `randomizeOrder = true`, `Agent`s will be activated in random order, otherwise in the order they were added to the `Environment`. **This currently defaults to `false` but will default to `true` in v0.6.0.**
169
+ *
170
+ * ```js
171
+ * // Ticks three times, activating 10 random agents with each tick cycle.
172
+ * environment.tick({
173
+ * activation: "random",
174
+ * activationCount: 10,
175
+ * count: 3
176
+ * });
177
+ * ```
178
+ *
106
179
  * @since 0.0.5
107
180
  */
108
181
  tick(opts?: number | TickOptions): void;
109
182
  /**
110
- * Use a helper with this environment.
111
- * @param {EnvironmentHelper} e
183
+ * Use a helper with this environment. A helper can be one of:
184
+ * - {@linkcode KDTree}
185
+ * - {@linkcode Network}
186
+ * - {@linkcode Terrain}
112
187
  * @since 0.1.3
113
188
  */
114
- use(e: EnvironmentHelper): void;
189
+ use(helper: EnvironmentHelper): void;
115
190
  /**
116
191
  * Get an array of data associated with agents in the environment by key.
117
- * Equivalent to calling `environment.getAgents().map(agent => agent.get(key));`
118
- * Defaults to calculating and storing the result within the same environment tick.
119
- * If the 2nd parameter is set to `false`, will recalculate and return the result every time.
120
- * @param {string} key - The key for which to retrieve data.
121
- * @param {boolean} useCache - Whether or not to cache the result (defaults to true).
122
- * @return {any[]} Array of data associated with `agent.get(key)` across all agents.
192
+ * Calling `environment.stat('name')` is equivalent to calling
193
+ * `environment.getAgents().map(agent => agent.get('name'));`
194
+ *
195
+ * By default, calling this will calculate the result at most once
196
+ * per time cycle, and return the cached value on subsequent calls (until
197
+ * the next time cycle, when it will recalculate).
198
+ *
199
+ * @param key - The key for which to retrieve data.
200
+ * @param useCache - Whether or not to cache the result.
201
+ * @returns Array of data associated with `agent.get(key)` across all agents.
202
+ *
203
+ * ```js
204
+ * environment.addAgent(new Agent({ name: "Alice" }));
205
+ * environment.addAgent(new Agent({ name: "Bob" }));
206
+ * environment.addAgent(new Agent({ name: "Chaz" }));
207
+ *
208
+ * environment.stat('name'); // returns ['Alice', 'Bob', 'Chaz']
209
+ * ```
210
+ *
123
211
  * @since 0.3.14
124
212
  */
125
213
  stat(key: string, useCache?: boolean): any[];
126
214
  /**
127
215
  * Pass a function to cache and use the return value within the same environment tick.
128
- * @param {Function} fn - The function to memoize.
129
- * @return {any} The return value of the function that was passed.
216
+ * @param fn - The function to memoize.
217
+ * @return The return value of the function that was passed.
130
218
  * @since 0.3.14
219
+ *
220
+ * ```js
221
+ * // Within the same time cycle, this function will only be called once.
222
+ * // The cached value will be used on subsequent calls.
223
+ * const blueAgents = environment.memo(() => {
224
+ * return environment.getAgents().filter(a => a.get('color') === 'blue');
225
+ * });
226
+ * ```
131
227
  */
132
228
  memo(fn: Function, key?: string): any;
133
229
  }
@@ -3,11 +3,22 @@ import { Agent } from "../agents/Agent";
3
3
  import { Cell } from "../agents/Cell";
4
4
  import { Environment, TickOptions } from "./Environment";
5
5
  /**
6
- * @since 0.0.5
6
+ * A `GridEnvironment` is the **deprecated** version of a cellular automata.
7
+ * It's now recommended that you use a standard {@linkcode Environment} with a
8
+ * {@linkcode Terrain}. This class will be removed entirely in v0.6.0.
9
+ *
10
+ * In a `GridEnvironment` with an {@linkcode ASCIIRenderer}, {@linkcode Agent}s are rendered
11
+ * using their `"value"` data (a single character).
12
+ *
13
+ * @deprecated since 0.4.0
14
+ * @since 0.0.10
7
15
  */
8
16
  declare class GridEnvironment extends Environment {
9
17
  cells: Map<string, Cell>;
10
18
  _cellHashes: Array<string>;
19
+ /**
20
+ * Create a `GridEnvironment` with the given `width` and `height`.
21
+ */
11
22
  constructor(width?: number, height?: number);
12
23
  /**
13
24
  * Fill every cell of the grid with an agent
@@ -16,11 +27,12 @@ declare class GridEnvironment extends Environment {
16
27
  */
17
28
  fill(): void;
18
29
  /**
30
+ * @hidden
19
31
  * @since 0.1.0
20
32
  */
21
33
  normalize(x: number, y: number): Point;
22
34
  /**
23
- * For GridEnvironments, `addAgent` takes `x` and `y` values
35
+ * For `GridEnvironment`s, `addAgent` takes `x` and `y` values
24
36
  * and automatically adds a Agent to that cell coordinate.
25
37
  * @param {number} x_
26
38
  * @param {number} y_
@@ -29,8 +41,8 @@ declare class GridEnvironment extends Environment {
29
41
  */
30
42
  addAgentAt(x_?: number, y_?: number, agent?: Agent): Agent;
31
43
  /**
32
- * For GridEnvironments, `removeAgent` takes `x` and `y` values
33
- * and removes the Agent (if there is one) at that cell coordinate.
44
+ * For GridEnvironments, `removeAgentAt` takes `x` and `y` values
45
+ * and removes the `Agent` (if there is one) at that cell coordinate.
34
46
  * @param {number} x_
35
47
  * @param {number} y_
36
48
  * @since 0.1.0
@@ -99,17 +111,19 @@ declare class GridEnvironment extends Environment {
99
111
  neighbors(agent: Agent, radius?: number, moore?: boolean): Agent[];
100
112
  /**
101
113
  * Execute all cell rules.
114
+ * @hidden
102
115
  * @param { boolean } randomizeOrder
103
116
  */
104
117
  _executeCellRules(randomizeOrder: boolean): void;
105
118
  /**
106
119
  * Execute all enqueued cell rules.
120
+ * @hidden
107
121
  * @param { boolean } randomizeOrder
108
122
  */
109
123
  _executeEnqueuedCellRules(randomizeOrder: boolean): void;
110
124
  /**
111
- * Override/extend Environment.tick to include the
112
- * GridEnvironment's cells.
125
+ * Override/extend {@linkcode Environment.tick} to include the
126
+ * `GridEnvironment`'s cells.
113
127
  * @override
114
128
  * @param {number} opts
115
129
  */