flocc 0.5.21 → 0.5.23

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.
@@ -3,6 +3,23 @@ import { Agent } from "../agents/Agent";
3
3
  declare type StepToken = number | string | Step;
4
4
  interface Step extends Array<StepToken> {
5
5
  }
6
+ interface RuleDiagnostic {
7
+ path: string;
8
+ level: "error" | "warning";
9
+ message: string;
10
+ }
11
+ interface RuleFormatOptions {
12
+ indent?: string;
13
+ maxLineWidth?: number;
14
+ }
15
+ /**
16
+ * Operator info: maps operator names to their expected argument counts.
17
+ * `min` and `max` define the valid range. If `max` is Infinity, the operator is variadic.
18
+ */
19
+ interface OperatorArity {
20
+ min: number;
21
+ max: number;
22
+ }
6
23
  /**
7
24
  * The `Rule` class is an experimental interface for adding behavior to {@linkcode Agent}s. A `Rule` object may be used in place of a `tick` function to be added as `Agent` behavior using `agent.set('tick', tickRule)`. As a trivial example, consider the following `Rule`, which increments the `Agent`'s `x` value with every time step:
8
25
  *
@@ -36,6 +53,23 @@ declare class Rule {
36
53
  locals: {
37
54
  [key: string]: any;
38
55
  };
56
+ /**
57
+ * When true, evaluation traces are logged and captured.
58
+ */
59
+ trace: boolean;
60
+ traceLog: string[];
61
+ /** @hidden */
62
+ private _traceDepth;
63
+ /**
64
+ * Static operator info mapping operator names to their expected argument counts.
65
+ */
66
+ static operatorInfo: {
67
+ [key: string]: OperatorArity;
68
+ };
69
+ /**
70
+ * Format arbitrary steps as pretty-printed S-expressions.
71
+ */
72
+ static formatSteps(steps: any[], options?: RuleFormatOptions): string;
39
73
  /**
40
74
  * A single step may be as simple as `["get", "x"]`. This returns the `Agent`'s `"x"` value to the outer step that contains it. So, for example, the step `["add", 1, ["get", "x"]]`, working from the inside out, retrieves the `"x"` value and then adds `1` to it. More complex steps function similarly, always traversing to the deepest nested step, evaluating it, and 'unwrapping' until all steps have been executed.
41
75
  *
@@ -67,18 +101,39 @@ declare class Rule {
67
101
  * |`"agent"`|`0`|No arguments; returns the `Agent`|
68
102
  * |`"environment"`|`0`|No arguments, returns the `Environment`|
69
103
  * |`"vector"`|`any`|Creates an n-dimensional {@linkcode Vector} from the supplied arguments|
104
+ * |`"log"`|`any`|Logs expression(s) and returns the last evaluated value|
70
105
  */
71
106
  constructor(environment: Environment, steps: Step[]);
107
+ /**
108
+ * Pretty-print the rule's step tree as S-expressions.
109
+ */
110
+ format(options?: RuleFormatOptions): string;
111
+ /**
112
+ * Returns a formatted S-expression representation of the rule.
113
+ */
114
+ toString(): string;
115
+ /**
116
+ * Validate the rule's step tree and return an array of diagnostics.
117
+ * Does not throw — returns diagnostics for inspection.
118
+ * @since 0.6.0
119
+ */
120
+ validate(): RuleDiagnostic[];
121
+ /** @hidden */
122
+ private _validateStep;
72
123
  /**
73
124
  * interpret single array step
74
125
  * @since 0.3.0
75
126
  * @hidden
76
127
  */
128
+ /** @hidden */
129
+ private _traceLogEntry;
77
130
  evaluate: (agent: Agent, step: any[]) => any;
131
+ /** @hidden */
132
+ private _evaluateOp;
78
133
  /**
79
134
  * @since 0.3.0
80
135
  * @hidden
81
136
  */
82
137
  call(agent: Agent): any;
83
138
  }
84
- export { Rule };
139
+ export { Rule, RuleDiagnostic, RuleFormatOptions };
package/dist/main.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { Agent } from "./agents/Agent";
2
2
  export { Vector } from "./helpers/Vector";
3
3
  export { Network } from "./helpers/Network";
4
- export { Rule } from "./helpers/Rule";
4
+ export { Rule, RuleDiagnostic, RuleFormatOptions } from "./helpers/Rule";
5
5
  export { KDTree } from "./helpers/KDTree";
6
6
  export { NumArray } from "./helpers/NumArray";
7
7
  export { Colors, Terrain } from "./helpers/Terrain";
@@ -1,6 +1,11 @@
1
1
  /// <reference path="../src/renderers/CanvasRendererOptions.d.ts" />
2
2
  import { AbstractRenderer } from "./AbstractRenderer";
3
3
  import type { Environment } from "../environments/Environment";
4
+ import type { Agent } from "../agents/Agent";
5
+ /** @hidden */
6
+ declare type InteractiveEventName = "click" | "hover" | "unhover";
7
+ /** @hidden */
8
+ declare type InteractiveCallback = (agent: Agent, event: MouseEvent) => void;
4
9
  /**
5
10
  * A `CanvasRenderer` renders an {@linkcode Environment} spatially in two dimensions.
6
11
  * Importantly, it expects that all {@linkcode Agent}s in the `Environment`
@@ -19,6 +24,12 @@ import type { Environment } from "../environments/Environment";
19
24
  * - `"triangle"` &mdash; Draws a triangle centered at the `Agent`'s `"x"` / `"y"` values.
20
25
  * - Also uses the `"size"` value.
21
26
  *
27
+ * When `interactive` is set to `true` in the options, the renderer supports:
28
+ * - **Click/hover detection** &mdash; Use {@linkcode on} to listen for `"click"`, `"hover"`, and `"unhover"` events on agents.
29
+ * - **Agent selection** &mdash; Clicking an agent selects it (highlighted with a stroke). Access selected agents via {@linkcode selected}.
30
+ * - **Pan** &mdash; Click and drag on empty space to pan.
31
+ * - **Zoom** &mdash; Scroll to zoom in/out (bounded by `zoomMin` / `zoomMax`).
32
+ *
22
33
  * @since 0.0.11
23
34
  */
24
35
  declare class CanvasRenderer extends AbstractRenderer {
@@ -28,6 +39,20 @@ declare class CanvasRenderer extends AbstractRenderer {
28
39
  buffer: HTMLCanvasElement;
29
40
  /** @hidden */
30
41
  terrainBuffer: HTMLCanvasElement;
42
+ /** The currently selected agents (only used when `interactive` is `true`). */
43
+ selected: Agent[];
44
+ /** @hidden */
45
+ private _listeners;
46
+ /** @hidden */
47
+ private _hoveredAgent;
48
+ /** @hidden */
49
+ private _isPanning;
50
+ /** @hidden */
51
+ private _panStart;
52
+ /** @hidden */
53
+ private _panOriginStart;
54
+ /** @hidden */
55
+ private _boundHandlers;
31
56
  /**
32
57
  * The first parameter must be the {@linkcode Environment} that this
33
58
  * `CanvasRenderer` will render.
@@ -39,12 +64,40 @@ declare class CanvasRenderer extends AbstractRenderer {
39
64
  * - `connectionOpacity` (*number* = `1`) &mdash; For `Environment`s using a `Network`, the opacity of lines
40
65
  * - `connectionWidth` (*number* = `1`) &mdash; For `Environment`s using a `Network`, the width of lines
41
66
  * - `height` (*number* = `500`) &mdash; The height, in pixels, of the canvas on which to render
67
+ * - `interactive` (*boolean* = `false`) &mdash; Enables interactive features (click/hover detection, selection, pan, zoom)
68
+ * - `onSelect` (*function*) &mdash; Optional callback when an agent is selected or deselected
42
69
  * - `origin` (*{ x: number; y: number }* = `{ x: 0, y: 0 }`) &mdash; The coordinate of the upper-left point of the space to be rendered
43
70
  * - `scale` (*number* = `1`) &mdash; The scale at which to render (the larger the scale, the smaller the size of the space that is actually rendered)
44
71
  * - `trace` (*boolean* = `false`) &mdash; If `true`, the renderer will not clear old drawings, causing the `Agent`s to appear to *trace* their paths across space
45
72
  * - `width` (*number* = `500`) &mdash; The width, in pixels, of the canvas on which to render
73
+ * - `zoomMin` (*number* = `0.1`) &mdash; Minimum scale when zooming
74
+ * - `zoomMax` (*number* = `10`) &mdash; Maximum scale when zooming
46
75
  */
47
76
  constructor(environment: Environment, opts: CanvasRendererOptions);
77
+ /**
78
+ * Register a callback for an interactive event.
79
+ * Supported event names: `"click"`, `"hover"`, `"unhover"`.
80
+ *
81
+ * ```js
82
+ * renderer.on("click", (agent, event) => {
83
+ * console.log("Clicked agent:", agent.id);
84
+ * });
85
+ * ```
86
+ *
87
+ * @param eventName - The event to listen for.
88
+ * @param callback - The callback, invoked with the `Agent` and the `MouseEvent`.
89
+ */
90
+ on(eventName: InteractiveEventName, callback: InteractiveCallback): void;
91
+ /** @hidden */
92
+ private _emit;
93
+ /**
94
+ * Given a mouse event, return the agent at that position (if any).
95
+ * Hit-testing accounts for the agent's shape and size.
96
+ * @hidden
97
+ */
98
+ _agentAtPoint(clientX: number, clientY: number): Agent | null;
99
+ /** @hidden */
100
+ private _setupInteractiveListeners;
48
101
  /** @hidden */
49
102
  x(v: number): number;
50
103
  /** @hidden */
@@ -67,6 +120,11 @@ declare class CanvasRenderer extends AbstractRenderer {
67
120
  drawRect(x: number, y: number, width: number, height: number): void;
68
121
  /** @hidden */
69
122
  drawRectWrap(x: number, y: number, w: number, h: number): void;
123
+ /**
124
+ * Draw a selection highlight around the given agent.
125
+ * @hidden
126
+ */
127
+ private _drawSelectionHighlight;
70
128
  render(): void;
71
129
  }
72
130
  export { CanvasRenderer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flocc",
3
- "version": "0.5.21",
3
+ "version": "0.5.23",
4
4
  "description": "Agent-based modeling in JavaScript in the browser or server.",
5
5
  "main": "dist/flocc.js",
6
6
  "module": "dist/flocc.es.js",
@@ -1,76 +0,0 @@
1
- /// <reference path="../src/agents/Agent.d.ts" />
2
- /// <reference path="../src/types/Data.d.ts" />
3
- /// <reference path="../src/renderers/Renderer.d.ts" />
4
- /// <reference path="../src/environments/EnvironmentHelper.d.ts" />
5
- /// <reference path="../src/environments/EnvironmentOptions.d.ts" />
6
- declare type NewRule = (agent: Agent) => Data;
7
- interface Helpers {
8
- kdtree: EnvironmentHelper;
9
- network: EnvironmentHelper;
10
- }
11
- export interface TickOptions {
12
- count?: number;
13
- randomizeOrder?: boolean;
14
- }
15
- export declare const defaultTickOptions: TickOptions;
16
- /**
17
- * From the parameter passed to .tick, get a structured TickOptions object.
18
- * @param {number | TickOptions} opts
19
- */
20
- export declare const getTickOptions: (opts?: number | TickOptions) => TickOptions;
21
- interface MemoValue {
22
- value: any;
23
- time: number;
24
- }
25
- declare class NewEnvironment {
26
- agents: number;
27
- cache: Map<string, MemoValue>;
28
- current: number;
29
- data: Map<string, any[]>;
30
- ids: string[];
31
- idsToIndices: {
32
- [key: string]: number;
33
- };
34
- helpers: Helpers;
35
- opts: EnvironmentOptions;
36
- nextData: Map<string, any[]>;
37
- rule: NewRule;
38
- renderers: Renderer[];
39
- width: number;
40
- height: number;
41
- time: number;
42
- constructor(opts?: EnvironmentOptions);
43
- static isAgent(a: any): a is Agent;
44
- addAgent(data: Data): Agent;
45
- /**
46
- * Remove an agent from the environment.
47
- * @param {Agent} agent
48
- */
49
- removeAgent(agent: Agent): void;
50
- /**
51
- * Remove an agent from the environment by its ID.
52
- * @param {string} id
53
- */
54
- removeAgentById(id: string): void;
55
- _get(i: number, key: string): any;
56
- _getData(i: number): Data;
57
- _set(i: number, key: string | Data, value?: any): void;
58
- increment(i: number, key: string, n: number): void;
59
- decrement(i: number, key: string, n: number): void;
60
- enqueue(i: number, data: Data): void;
61
- getAgent(i: number): Agent;
62
- getAgents(): Agent[];
63
- getAgentById(id: string): Agent;
64
- /**
65
- * Removes all agents from the environment.
66
- */
67
- clear(): void;
68
- addRule(rule: NewRule): void;
69
- tick(opts?: number | TickOptions): void;
70
- /**
71
- * Use a helper with this environment.
72
- * @param {EnvironmentHelper} e
73
- */
74
- use(e: EnvironmentHelper): void;
75
- }
76
- export { NewEnvironment };
@@ -1,6 +0,0 @@
1
- declare class BS {
2
- size: number;
3
- m: number;
4
- constructor(size: number);
5
- }
6
- export { BS };
@@ -1,2 +0,0 @@
1
- /// <reference path="../src/types/Point.d.ts" />
2
- export default function instanceOfPoint(obj: any): obj is Point;
@@ -1,2 +0,0 @@
1
- /// <reference path="../src/agents/Agent.d.ts" />
2
- export default function isAgent(a: any): a is Agent;
@@ -1,10 +0,0 @@
1
- /**
2
- * Copies the values of `source` to `arr`
3
- * or to a new Array.
4
- *
5
- * @private
6
- * @param {Array} source The Array to copy values from.
7
- * @param {Array} [arr=[]] The Array to copy values to.
8
- * @returns {Array}
9
- */
10
- export default function copyArray<T>(source: T[], arr?: T[]): T[];
@@ -1 +0,0 @@
1
- export default function lcg(modulus: number, a: number, c: number, seed: number): Generator<number>;
@@ -1,12 +0,0 @@
1
- export default class Randomizer {
2
- index: number;
3
- maxrange: number;
4
- offset: number;
5
- prime: number;
6
- runningvalue: number;
7
- constructor(maxrange: number);
8
- reset(): void;
9
- getCurrentValue(): number;
10
- hasNext(): boolean;
11
- next(): number;
12
- }