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.
package/dist/flocc.es.js CHANGED
@@ -372,10 +372,19 @@ function sum(arr) {
372
372
  }
373
373
 
374
374
  /**
375
- * Linearly interpolate between two values.
376
- * @param x {number} - The first value.
377
- * @param y {number} - The second value.
378
- * @param t {number} - The amount by which to interpolate (0 returns x, 1 returns y).
375
+ * Linearly interpolates between `x` and `y`. The third parameter `t` (usually
376
+ * a value between `0` and `1`) is the amount by which to interpolate — a value of `0`
377
+ * returns the `x` value and `1` returns the `y` value.
378
+ *
379
+ * ```js
380
+ * lerp(5, 10, 0.5); // returns 7.5
381
+ * lerp(0, 100, 0.1); // returns 10
382
+ * lerp(22, 79, 1); // returns 79
383
+ * ```
384
+ *
385
+ * @param x The first value.
386
+ * @param y The second value.
387
+ * @param t The amount by which to interpolate (0 returns x, 1 returns y).
379
388
  * @since 0.2.4
380
389
  */
381
390
  function lerp(x, y, t) {
@@ -386,7 +395,7 @@ function lerp(x, y, t) {
386
395
  * Copies the values of `source` to `arr`
387
396
  * or to a new Array.
388
397
  *
389
- * @private
398
+ * @hidden
390
399
  * @param {Array} source The Array to copy values from.
391
400
  * @param {Array} [arr=[]] The Array to copy values to.
392
401
  * @returns {Array}
@@ -403,6 +412,8 @@ function copyArray(source, arr) {
403
412
  }
404
413
 
405
414
  /**
415
+ * A `Vector` contains multi-dimensional numeric data.
416
+ *
406
417
  * @since 0.1.0
407
418
  */
408
419
  var Vector = /** @class */ (function () {
@@ -415,20 +426,40 @@ var Vector = /** @class */ (function () {
415
426
  this.dimension = data ? data.length : 0;
416
427
  }
417
428
  /**
429
+ * Retrieve a value from a `Vector` by its index. If the given index is greater than the
430
+ * `Vector`'s dimension, this returns `0` by default.
431
+ *
432
+ * ```js
433
+ * const v = new Vector(1, 2, 4);
434
+ *
435
+ * v.index(0); // returns 1
436
+ * v.index(2); // returns 4
437
+ * v.index(5); // returns 0
438
+ * ```
418
439
  * @since 0.1.0
419
440
  */
420
- Vector.prototype.index = function (n) {
421
- if (this.dimension > n) {
422
- return this.data[n];
441
+ Vector.prototype.index = function (i) {
442
+ if (this.dimension > i) {
443
+ return this.data[i];
423
444
  }
424
445
  // Attempting to access index ${n} on a vector greater than the vector's dimension returns 0 by default
425
446
  return 0;
426
447
  };
427
448
  /**
428
- * Overwrite the value at a given index or position. If the index is beyond the dimension of this vector,
429
- * the dimension will be increased to the dimensionality implied by the index.
430
- * @param i {number | string} - The numerical index (0-based) or lowercase string value ('x') to set.
431
- * @param value {number} - The value to set at this index/position.
449
+ * Set the value at a given index. If the index is greater than the {@linkcode dimension}
450
+ * of this `Vector`, the dimension will be increased to the dimensionality implied by the index.
451
+ * @param i The numerical index (0-based) or lowercase string value (e.g. `"x"`) to set.
452
+ * @param value The value to set at this index/position.
453
+ *
454
+ * ```js
455
+ * const vector = new Vector();
456
+ * vector.set(0, 10);
457
+ * vector.set('y', 2);
458
+ * vector.set(2, 4);
459
+ *
460
+ * vector.xyz; // [10, 2, 4]
461
+ * ```
462
+ *
432
463
  * @since 0.1.0
433
464
  */
434
465
  Vector.prototype.set = function (i, value) {
@@ -456,128 +487,175 @@ var Vector = /** @class */ (function () {
456
487
  return this;
457
488
  };
458
489
  Object.defineProperty(Vector.prototype, "x", {
490
+ /** @since 0.1.0 */
459
491
  get: function () {
460
492
  return this.index(0);
461
493
  },
494
+ /** @since 0.1.0 */
462
495
  set: function (n) {
463
496
  this.set(0, n);
464
497
  },
465
- enumerable: true,
498
+ enumerable: false,
466
499
  configurable: true
467
500
  });
468
501
  Object.defineProperty(Vector.prototype, "y", {
502
+ /** @since 0.1.0 */
469
503
  get: function () {
470
504
  return this.index(1);
471
505
  },
506
+ /** @since 0.1.0 */
472
507
  set: function (n) {
473
508
  this.set(1, n);
474
509
  },
475
- enumerable: true,
510
+ enumerable: false,
476
511
  configurable: true
477
512
  });
478
513
  Object.defineProperty(Vector.prototype, "z", {
514
+ /** @since 0.1.0 */
479
515
  get: function () {
480
516
  return this.index(2);
481
517
  },
518
+ /** @since 0.1.0 */
482
519
  set: function (n) {
483
520
  this.set(2, n);
484
521
  },
485
- enumerable: true,
522
+ enumerable: false,
486
523
  configurable: true
487
524
  });
488
525
  Object.defineProperty(Vector.prototype, "w", {
526
+ /** @since 0.1.0 */
489
527
  get: function () {
490
528
  return this.index(3);
491
529
  },
530
+ /** @since 0.1.0 */
492
531
  set: function (n) {
493
532
  this.set(3, n);
494
533
  },
495
- enumerable: true,
534
+ enumerable: false,
496
535
  configurable: true
497
536
  });
498
537
  Object.defineProperty(Vector.prototype, "xy", {
538
+ /** @since 0.2.4 */
499
539
  get: function () {
500
540
  return [this.index(0), this.index(1)];
501
541
  },
502
- enumerable: true,
542
+ enumerable: false,
503
543
  configurable: true
504
544
  });
505
545
  Object.defineProperty(Vector.prototype, "xz", {
546
+ /** @since 0.2.4 */
506
547
  get: function () {
507
548
  return [this.index(0), this.index(2)];
508
549
  },
509
- enumerable: true,
550
+ enumerable: false,
510
551
  configurable: true
511
552
  });
512
553
  Object.defineProperty(Vector.prototype, "yz", {
554
+ /** @since 0.2.4 */
513
555
  get: function () {
514
556
  return [this.index(1), this.index(2)];
515
557
  },
516
- enumerable: true,
558
+ enumerable: false,
517
559
  configurable: true
518
560
  });
519
561
  Object.defineProperty(Vector.prototype, "xyz", {
562
+ /** @since 0.2.4 */
520
563
  get: function () {
521
564
  return [this.index(0), this.index(1), this.index(2)];
522
565
  },
523
- enumerable: true,
566
+ enumerable: false,
524
567
  configurable: true
525
568
  });
526
569
  Object.defineProperty(Vector.prototype, "r", {
570
+ /**
571
+ * `r` for 'red' (the 1st value)
572
+ * @since 0.1.0
573
+ */
527
574
  get: function () {
528
575
  return this.index(0);
529
576
  },
577
+ /**
578
+ * `r` for 'red' (the 1st value)
579
+ * @since 0.1.0
580
+ */
530
581
  set: function (n) {
531
582
  this.set(0, n);
532
583
  },
533
- enumerable: true,
584
+ enumerable: false,
534
585
  configurable: true
535
586
  });
536
587
  Object.defineProperty(Vector.prototype, "g", {
588
+ /**
589
+ * `g` for 'green' (the 2nd value)
590
+ * @since 0.1.0
591
+ */
537
592
  get: function () {
538
593
  return this.index(1);
539
594
  },
595
+ /**
596
+ * `g` for 'green' (the 2nd value)
597
+ * @since 0.1.0
598
+ */
540
599
  set: function (n) {
541
600
  this.set(1, n);
542
601
  },
543
- enumerable: true,
602
+ enumerable: false,
544
603
  configurable: true
545
604
  });
546
605
  Object.defineProperty(Vector.prototype, "b", {
606
+ /**
607
+ * `b` for 'blue' (the 3rd value)
608
+ * @since 0.1.0
609
+ */
547
610
  get: function () {
548
611
  return this.index(2);
549
612
  },
613
+ /**
614
+ * `b` for 'blue' (the 3rd value)
615
+ * @since 0.1.0
616
+ */
550
617
  set: function (n) {
551
618
  this.set(2, n);
552
619
  },
553
- enumerable: true,
620
+ enumerable: false,
554
621
  configurable: true
555
622
  });
556
623
  Object.defineProperty(Vector.prototype, "a", {
624
+ /**
625
+ * `a` for 'alpha' (the 4th value)
626
+ * @since 0.1.0
627
+ */
557
628
  get: function () {
558
629
  return this.index(3);
559
630
  },
631
+ /**
632
+ * `a` for 'alpha' (the 4th value)
633
+ * @since 0.1.0
634
+ */
560
635
  set: function (n) {
561
636
  this.set(3, n);
562
637
  },
563
- enumerable: true,
638
+ enumerable: false,
564
639
  configurable: true
565
640
  });
566
641
  Object.defineProperty(Vector.prototype, "rgb", {
642
+ /** @since 0.2.4 */
567
643
  get: function () {
568
644
  return [this.index(0), this.index(1), this.index(2)];
569
645
  },
570
- enumerable: true,
646
+ enumerable: false,
571
647
  configurable: true
572
648
  });
573
649
  Object.defineProperty(Vector.prototype, "rgba", {
650
+ /** @since 0.2.4 */
574
651
  get: function () {
575
652
  return [this.index(0), this.index(1), this.index(2), this.index(3)];
576
653
  },
577
- enumerable: true,
654
+ enumerable: false,
578
655
  configurable: true
579
656
  });
580
657
  /**
658
+ * Add another `Vector` to this `Vector`. This *does* mutate the `Vector` that calls this method.
581
659
  * @since 0.1.0
582
660
  */
583
661
  Vector.prototype.add = function (v) {
@@ -592,6 +670,17 @@ var Vector = /** @class */ (function () {
592
670
  return this;
593
671
  };
594
672
  /**
673
+ * Multiply this `Vector` by a scalar number. This *does* mutate the `Vector` that calls this method.
674
+ *
675
+ * ```js
676
+ * const v = new Vector(1, 2);
677
+ * v.multiplyScalar(5);
678
+ * v.xy; // returns [5, 10]
679
+ *
680
+ * v.multiplyScalar(-0.5);
681
+ * v.xy; // returns [-2.5, -5]
682
+ * ```
683
+ *
595
684
  * @since 0.1.0
596
685
  */
597
686
  Vector.prototype.multiplyScalar = function (n) {
@@ -599,6 +688,7 @@ var Vector = /** @class */ (function () {
599
688
  return this;
600
689
  };
601
690
  /**
691
+ * Add a scalar number to all of this `Vector`'s values'. This *does* mutate the `Vector` that calls this method.
602
692
  * @since 0.1.0
603
693
  */
604
694
  Vector.prototype.addScalar = function (n) {
@@ -613,8 +703,14 @@ var Vector = /** @class */ (function () {
613
703
  return Math.sqrt(sum(this.data.map(function (x) { return Math.pow(x, 2); })));
614
704
  };
615
705
  /**
616
- * Normalize the vector (turn it into a vector with length = 1).
617
- * Has no effect on the 0 vector.
706
+ * Normalize the `Vector` (turn it into a `Vector` with length = `1`). Has no effect on the 0 `Vector`. This *does* mutate the `Vector` that calls this method.
707
+ *
708
+ * ```js
709
+ * const v = new Vector(5, 3, -1);
710
+ * v.normalize();
711
+ * v.length(); // returns 1
712
+ * ```
713
+ *
618
714
  * @since 0.1.0
619
715
  */
620
716
  Vector.prototype.normalize = function () {
@@ -625,6 +721,7 @@ var Vector = /** @class */ (function () {
625
721
  return this;
626
722
  };
627
723
  /**
724
+ * Create a copy of this `Vector`.
628
725
  * @since 0.1.0
629
726
  */
630
727
  Vector.prototype.clone = function () {
@@ -632,8 +729,15 @@ var Vector = /** @class */ (function () {
632
729
  return new (Vector.bind.apply(Vector, __spreadArrays([void 0], data)))();
633
730
  };
634
731
  /**
635
- * Rotate a vector about the Z axis.
636
- * @param angle {number} - The angle by which to rotate the vector, in radians
732
+ * Rotate the `Vector` about the z-axis by `angle` radians (updating its `x` and `y` values). This *does* mutate the `Vector` that calls this method.
733
+ *
734
+ * ```js
735
+ * const v = new Vector(1, 0);
736
+ * v.rotateZ(Math.PI / 2); // rotate by PI / 2 radians = 90 degrees
737
+ *
738
+ * v.xy; // returns [0, 1]
739
+ * ```
740
+ *
637
741
  * @since 0.2.2
638
742
  */
639
743
  Vector.prototype.rotateZ = function (angle) {
@@ -646,8 +750,8 @@ var Vector = /** @class */ (function () {
646
750
  return this;
647
751
  };
648
752
  /**
649
- * Get the dot product of this vector with another.
650
- * @param {Vector} v - The other vector.
753
+ * Get the {@link https://en.wikipedia.org/wiki/Dot_product | dot product} of this `Vector` with another.
754
+ * @since 0.2.4
651
755
  */
652
756
  Vector.prototype.dot = function (v) {
653
757
  var dimension = Math.max(this.dimension, v.dimension);
@@ -657,11 +761,23 @@ var Vector = /** @class */ (function () {
657
761
  return sum;
658
762
  };
659
763
  /**
660
- * Linearly interpolate between this vector and another vector.
661
- * Note that this method returns a new vector and does not mutate the vector on which it is called!
662
- * @param {Vector} v - The other vector.
663
- * @param {number} t - The amount by which to interpolate.
764
+ * Linearly interpolate between this `Vector` and another `Vector`. This *does not* mutate the original `Vector` that calls this method, but returns a new `Vector`.
765
+ *
766
+ * ```js
767
+ * const a = new Vector(1, 3, -5);
768
+ * const b = new Vector(4, -2);
769
+ *
770
+ * a.lerp(b, 0); // returns a clone of Vector a
771
+ * a.lerp(b, 1); // returns a clone of Vector b
772
+ *
773
+ * const mid = a.lerp(b, 0.5); // returns a Vector halfway between a and b
774
+ * mid.xyz; // returns [2.5, 0.5, -2.5]
775
+ * ```
776
+ *
777
+ * @param v - The other vector.
778
+ * @param t - The amount by which to interpolate (usually between `0` and `1`, although it can be any number).
664
779
  * @returns {Vector} - The new, interpolated vector.
780
+ * @since 0.2.4
665
781
  */
666
782
  Vector.prototype.lerp = function (v, t) {
667
783
  var longerVector = this.dimension > v.dimension ? this : v;
@@ -726,16 +842,70 @@ var method = function (obj, name) {
726
842
  return obj[name].apply(obj, args);
727
843
  };
728
844
  /**
845
+ * 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:
846
+ *
847
+ * ```js
848
+ * const rule = new Rule(environment, [
849
+ * "set", "x", [
850
+ * "add", 1, [
851
+ * "get", "x"
852
+ * ]
853
+ * ]
854
+ * ]);
855
+ * agent.set("tick", rule);
856
+ * ```
857
+ *
858
+ * Reading from the outer arrays inward, the steps of this `Rule` instructs the `Agent` to:
859
+ * - `set` the `Agent`'s `"x"` value to...
860
+ * - The result of `add`ing `1` and...
861
+ * - The `Agent`'s current `"x"` value
862
+ *
863
+ * Generally, `Rule` steps are a deeply nested array, where the first value of any given array is always an instruction or operator (e.g. `"set"`, `"add"`, `"filter"`). See the {@linkcode constructor} function for more information about steps.
729
864
  * @since 0.3.0
730
865
  */
731
866
  var Rule = /** @class */ (function () {
867
+ /**
868
+ * 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.
869
+ *
870
+ * A step's first element should be a string that is one of the allowed operators, followed by a certain number of arguments.
871
+ *
872
+ * |Operator|Arguments|Notes|
873
+ * |---|---|---|
874
+ * |`"add"`|`2`|Pass 2 numbers, or two steps that evaluate to numbers|
875
+ * |`"subtract"`|`2`|""|
876
+ * |`"multiply"`|`2`|""|
877
+ * |`"divide"`|`2`|""|
878
+ * |`"mod"`|`2`|""|
879
+ * |`"power"`|`2`|""|
880
+ * |`"get"`|`1`|Pass the key of `Agent` data to retrieve|
881
+ * |`"set"`|`2`|Pass the key and value to set|
882
+ * |`"enqueue"`|`2`|Pass the key and value to enqueue|
883
+ * |`"local"`|`2`|Pass the key and value to set as local variables|
884
+ * |`"if"`|`3`|Pass the conditional (usually a step that evaluates to a boolean), the step to run when `true`, and the step to run when `false|
885
+ * |`"and"`|`2`|Pass the two steps to logically evaluate|
886
+ * |`"or"`|`2`|""|
887
+ * |`"gt"`|`2`|""|
888
+ * |`"gte"`|`2`|""|
889
+ * |`"lt"`|`2`|""|
890
+ * |`"lte"`|`2`|""|
891
+ * |`"eq"`|`2`|""|
892
+ * |`"map"`|`2`|Pass an array (or step that evaluates to an array) and a lambda to invoke for each element|
893
+ * |`"filter"`|`2`|""|
894
+ * |`"key"`|`2`|Pass an object (or step that evaluates to an object) and the key to retrieve from that object|
895
+ * |`"agent"`|`0`|No arguments; returns the `Agent`|
896
+ * |`"environment"`|`0`|No arguments, returns the `Environment`|
897
+ * |`"vector"`|`any`|Creates an n-dimensional {@linkcode Vector} from the supplied arguments|
898
+ */
732
899
  function Rule(environment, steps) {
733
900
  var _this = this;
901
+ /** @hidden */
734
902
  this.steps = [];
903
+ /** @hidden */
735
904
  this.locals = {};
736
905
  /**
737
906
  * interpret single array step
738
907
  * @since 0.3.0
908
+ * @hidden
739
909
  */
740
910
  this.evaluate = function (agent, step) {
741
911
  var first = step && step.length > 0 ? step[0] : null;
@@ -860,6 +1030,7 @@ var Rule = /** @class */ (function () {
860
1030
  }
861
1031
  /**
862
1032
  * @since 0.3.0
1033
+ * @hidden
863
1034
  */
864
1035
  Rule.prototype.call = function (agent) {
865
1036
  return this.evaluate(agent, this.steps);
@@ -915,40 +1086,85 @@ var disallowed = ["tick", "queue"];
915
1086
  var warnOnce1 = once(console.warn.bind(console));
916
1087
  var warnOnce2 = once(console.warn.bind(console));
917
1088
  /**
1089
+ * This class puts the `Agent` in 'agent-based modeling.' More specifically,
1090
+ * an `Agent` represents an individual unit of data and its associated
1091
+ * behaviors.
918
1092
  * @since 0.0.5
919
1093
  */
920
1094
  var Agent = /** @class */ (function () {
1095
+ /**
1096
+ * `Agent`s can be instantiated with or without data. Instantiating
1097
+ * with data is equivalent to creating an `Agent` and immediately
1098
+ * calling {@linkcode Agent.set} to add data.
1099
+ *
1100
+ * ```js
1101
+ * // instantiates an Agent without data
1102
+ * const a = new Agent();
1103
+ *
1104
+ * // instantiates an Agent with data
1105
+ * const b = new Agent({
1106
+ * x: 50,
1107
+ * y: 100
1108
+ * });
1109
+ * ```
1110
+ * @param data
1111
+ */
921
1112
  function Agent(data) {
922
1113
  if (data === void 0) { data = {}; }
923
1114
  /**
924
- * @member {Environment|null} environment
925
- * @member {RuleObj[]} rules
926
- * @member {RuleObj[]} queue
927
- * @member {Object} data
1115
+ * An `Agent` can only belong to a single {@linkcode Environment}. When
1116
+ * `environment.addAgent(agent);` is called, this is value is updated
1117
+ * to point to that `Environment`.
1118
+ *
1119
+ * ```js
1120
+ * const environment = new Environment();
1121
+ * const agent = new Agent();
1122
+ * agent.environment; // returns `null`
1123
+ *
1124
+ * environment.addAgent(agent);
1125
+ * agent.environment === environment; // returns `true`
928
1126
  */
929
1127
  this.environment = null;
1128
+ /** @hidden */
930
1129
  this.rules = [];
1130
+ /** @hidden */
931
1131
  this.queue = [];
1132
+ /** @hidden */
932
1133
  this.data = {};
1134
+ /**
1135
+ * `Agent`s are automatically assigned a unique ID when they are created.
1136
+ * This can be useful when you need to refer to a specific `Agent`, and
1137
+ * they can be retrieved using their ID from their `Environment` by calling
1138
+ * {@link Environment.getAgentById | `environment.getAgentById(id);`}
1139
+ * ```js
1140
+ * const agent = new Agent();
1141
+ * const id = agent.id; // returns "59B4F928-46C8-..." (for example)
1142
+ * ```
1143
+ */
933
1144
  this.id = uuid$1();
934
- // This is used as a temporary store for data that
935
- // gets returned from rules. When enqueued rules are executed,
936
- // even if there aren't any enqueued rules, .set gets called
937
- // on any data that was placed here.
1145
+ /**
1146
+ * This is used as a temporary store for data that
1147
+ * gets returned from rules. When enqueued rules are executed,
1148
+ * even if there aren't any enqueued rules, .set gets called
1149
+ * on any data that was placed here.
1150
+ * @hidden
1151
+ */
938
1152
  this.__newData = {};
939
- // When agent.get('key') is called, this pseudo-private member is set to 'key'.
940
- // Once it is retrieved, it is reset to null. If agent.get('key') is called before
941
- // this has been reset, that means that there is an infinite loop, and the call
942
- // will throw an error.
1153
+ /** When agent.get('key') is called, this pseudo-private member is set to 'key'.
1154
+ * Once it is retrieved, it is reset to null. If agent.get('key') is called before
1155
+ * this has been reset, that means that there is an infinite loop, and the call
1156
+ * will throw an error.
1157
+ * @hidden
1158
+ */
943
1159
  this.__retrievingData = null;
1160
+ /** @hidden */
944
1161
  this.__subtree = null;
945
1162
  this.set(data);
946
1163
  }
947
1164
  /**
948
1165
  * Set a function value. `tick` and `queue` are not automatically called,
949
1166
  * but any other named value will automatically be called when referenced.
950
- * @param {string} name
951
- * @param {Function} fn
1167
+ * @hidden
952
1168
  */
953
1169
  Agent.prototype._setFunctionValue = function (name, fn) {
954
1170
  var _this = this;
@@ -964,9 +1180,8 @@ var Agent = /** @class */ (function () {
964
1180
  }
965
1181
  };
966
1182
  /**
967
- * Retrieve an arbitrary piece of data associated
968
- * with this agent by name.
969
- * @param {string} name
1183
+ * Retrieve an arbitrary piece of data associated by name.
1184
+ * If the data has not been {@linkcode set}, returns `null`.
970
1185
  * @since 0.0.5
971
1186
  */
972
1187
  Agent.prototype.get = function (name) {
@@ -984,8 +1199,20 @@ var Agent = /** @class */ (function () {
984
1199
  return data;
985
1200
  };
986
1201
  /**
987
- * Retrieve all the data associated with this agent
988
- * (useful for destructuring properties).
1202
+ * Retrieve all the data associated with this `Agent` at once.
1203
+ *
1204
+ * ```js
1205
+ * agent.set('x', 3);
1206
+ * agent.set('color', 'blue');
1207
+ * agent.set('active', false);
1208
+ *
1209
+ * agent.getData();
1210
+ * // returns {
1211
+ * // x: 3,
1212
+ * // color: 'blue',
1213
+ * // active: false
1214
+ * // }
1215
+ * ```
989
1216
  * @since 0.1.0
990
1217
  */
991
1218
  Agent.prototype.getData = function () {
@@ -1019,6 +1246,7 @@ var Agent = /** @class */ (function () {
1019
1246
  /**
1020
1247
  * Helper function to set key-value pair depending on whether value
1021
1248
  * is a function (callable) or not
1249
+ * @hidden
1022
1250
  */
1023
1251
  Agent.prototype._setKeyValue = function (key, value) {
1024
1252
  if (typeof value === "function") {
@@ -1057,25 +1285,57 @@ var Agent = /** @class */ (function () {
1057
1285
  }
1058
1286
  };
1059
1287
  /**
1060
- * Increment a numeric (assume integer) piece of data
1061
- * associated with this agent. If `n` is included, increments by
1062
- * `n`. If the value has not yet been set, initializes it to 1.
1063
- * @param {string} name
1064
- * @param {number} n
1288
+ * increment a numeric piece of data associated with this `Agent`
1289
+ * (increasing its value by 1). This method is *synchronous* —
1290
+ * it immediately increases the value (to *asynchronously* increase it,
1291
+ * the rule function should instead return a new value.
1292
+ *
1293
+ * ```js
1294
+ * agent.set('x', 50);
1295
+ * agent.increment('x');
1296
+ * agent.get('x'); // returns 51
1297
+ * ```
1298
+ *
1299
+ * If the second parameter `n` is included, decrements by that amount.
1300
+ *
1301
+ * ```js
1302
+ * agent.set('x', 50);
1303
+ * agent.increment('x', 10);
1304
+ * agent.get('x'); // returns 60
1305
+ * ```
1306
+ *
1307
+ * If the value has not yet been set, calling this method sets it to `1`
1308
+ * (or to `n`).
1065
1309
  * @since 0.0.8
1066
1310
  */
1067
1311
  Agent.prototype.increment = function (name, n) {
1068
1312
  if (n === void 0) { n = 1; }
1069
- if (!this.get(name))
1313
+ if (this.get(name) === null)
1070
1314
  this.set(name, 0);
1071
1315
  this.set(name, this.get(name) + n);
1072
1316
  };
1073
1317
  /**
1074
- * Decrement a numeric (assume integer) piece of data
1075
- * associated with this agent. If `n` is included, decrements by
1076
- * `n`. If the value has not yet been set,
1077
- * initializes it to -1.
1078
- * @param {string} name
1318
+ * Decrement a numeric piece of data associated with this `Agent`
1319
+ * (decreasing its value by 1). This method is *synchronous* —
1320
+ * it immediately decreases the value (to *asynchronously* decrease it,
1321
+ * the rule function should instead return a new value.
1322
+ *
1323
+ * ```js
1324
+ * agent.set('x', 50);
1325
+ * agent.decrement('x');
1326
+ * agent.get('x'); // returns 49
1327
+ * ```
1328
+ *
1329
+ * If the second parameter `n` is included, decrements by that amount.
1330
+ *
1331
+ * ```js
1332
+ * agent.set('x', 50);
1333
+ * agent.decrement('x', 10);
1334
+ * agent.get('x'); // returns 40
1335
+ * ```
1336
+ *
1337
+ * If the value has not yet been set, calling this method sets it to `-1`
1338
+ * (or to `-n`).
1079
1339
  * @since 0.0.8
1080
1340
  */
1081
1341
  Agent.prototype.decrement = function (name, n) {
@@ -1083,9 +1343,29 @@ var Agent = /** @class */ (function () {
1083
1343
  this.increment(name, -n);
1084
1344
  };
1085
1345
  /**
1086
- * Add a rule to be executed during the agent's
1087
- * environment's tick cycle. When executed, the
1088
- * @param {Function | Rule} rule
1346
+ * Until v0.5.14, this was the preferred way to add behavior to `Agent`s.
1347
+ * Now, the preferred method is by setting the `Agent`'s `"tick"` value (i.e. `agent.set({ tick: function(agt) { ... }})`).
1348
+ * This method will still be allowed until v0.7.0.
1349
+ *
1350
+ * 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}.
1351
+ * It is possible to add *more than one rule* to an `Agent`, although it
1352
+ * is generally easier to write a longer function or to break it apart
1353
+ * into multiple functions.
1354
+ *
1355
+ * ```js
1356
+ * // adds a rule that *synchronously* increments the Agent's "x" value
1357
+ * agent.addRule(function(agt) {
1358
+ * agent.increment('x');
1359
+ * });
1360
+ *
1361
+ * // adds a rule that *asynchronously* increments the Agent's "x" value
1362
+ * agent.addRule(function(agt) {
1363
+ * return {
1364
+ * x: agt.get('x') + 1
1365
+ * };
1366
+ * });
1367
+ * ```
1368
+ *
1089
1369
  * @deprecated since version 0.5.14
1090
1370
  * @since 0.0.5
1091
1371
  */
@@ -1101,16 +1381,34 @@ var Agent = /** @class */ (function () {
1101
1381
  });
1102
1382
  };
1103
1383
  /**
1104
- * Enqueue a function to be executed at the end of
1105
- * the agent's environment's tick cycle (for example,
1106
- * if agents in an environment should perform their
1107
- * calculations and updates separately). Additional/external
1108
- * data passed in as arguments to the enqueued function will
1384
+ * Like {@linkcode Agent.addRule}, this method is deprecated and the
1385
+ * recommended way is to now call
1386
+ * `agent.set('queue', function(agt) { ... });`
1387
+ *
1388
+ * Calling this method enqueues a function to be executed
1389
+ * *asynchronously* (at the end of the {@linkcode Environment}'s tick cycle).
1390
+ * This is useful if a 'cleanup pass' should be performed between
1391
+ * time steps to adjust `Agent` data.
1392
+ *
1393
+ * Below, the `Agent` sets its `"x"` value to `30` whenever it is
1394
+ * activated during the `Environment`'s tick cycle. After all of that
1395
+ * cycle's `Agent`s have been activated, this `Agent` sets its `"x"`
1396
+ * value to `20`. So if any other `Agent` references its `"x"` value
1397
+ * during a tick cycle after it has been activated, it will return `30`,
1398
+ * but in between tick cycles it will return `20`.
1399
+ *
1400
+ * ```js
1401
+ * agent.addRule(agt => {
1402
+ * agt.set("x", 30);
1403
+ * agt.enqueue(a => {
1404
+ * a.set("x", 20);
1405
+ * });
1406
+ * });
1407
+ * ```
1408
+ *
1409
+ * Any additional parameters passed to the enqueued function will
1109
1410
  * be remembered and passed through when the function is executed.
1110
1411
  *
1111
- * The `queue` array is cleared at the very end of
1112
- * the environment's tick cycle.
1113
- * @param {Function} enqueuedRule
1114
1412
  * @deprecated since version 0.5.14
1115
1413
  * @since 0.0.5
1116
1414
  */
@@ -1127,7 +1425,7 @@ var Agent = /** @class */ (function () {
1127
1425
  };
1128
1426
  /**
1129
1427
  * From a RuleObj, execute a single rule (function or structured Rule).
1130
- * @param {RuleObj} ruleObj
1428
+ * @hidden
1131
1429
  */
1132
1430
  Agent.prototype.executeRule = function (ruleObj) {
1133
1431
  var rule = ruleObj.rule, args = ruleObj.args;
@@ -1142,6 +1440,7 @@ var Agent = /** @class */ (function () {
1142
1440
  };
1143
1441
  /**
1144
1442
  * Execute all rules.
1443
+ * @hidden
1145
1444
  */
1146
1445
  Agent.prototype.executeRules = function () {
1147
1446
  var _this = this;
@@ -1158,6 +1457,7 @@ var Agent = /** @class */ (function () {
1158
1457
  };
1159
1458
  /**
1160
1459
  * Execute all enqueued rules.
1460
+ * @hidden
1161
1461
  */
1162
1462
  Agent.prototype.executeEnqueuedRules = function () {
1163
1463
  // if new data from the rules
@@ -1187,9 +1487,15 @@ var Agent = /** @class */ (function () {
1187
1487
  }());
1188
1488
 
1189
1489
  /**
1190
- * Find the mean value of an Array of numbers.
1191
- * @param {Array<number>} arr
1192
- * @returns {number}
1490
+ * Return the mean value from an array of numbers.
1491
+ *
1492
+ * ```js
1493
+ * mean([1, 2, 3]); // returns 2
1494
+ * mean([10]); // returns 10
1495
+ *
1496
+ * mean([]); // returns null for empty arrays
1497
+ * ```
1498
+ *
1193
1499
  * @since 0.0.16
1194
1500
  */
1195
1501
  function mean(arr) {
@@ -1224,6 +1530,7 @@ function shuffle(array) {
1224
1530
  }
1225
1531
 
1226
1532
  /**
1533
+ * @hidden
1227
1534
  * @since 0.3.11
1228
1535
  */
1229
1536
  var NumArray = /** @class */ (function () {
@@ -1235,7 +1542,7 @@ var NumArray = /** @class */ (function () {
1235
1542
  get: function () {
1236
1543
  return this._index;
1237
1544
  },
1238
- enumerable: true,
1545
+ enumerable: false,
1239
1546
  configurable: true
1240
1547
  });
1241
1548
  NumArray.prototype.set = function (i, n) {
@@ -1286,24 +1593,33 @@ var Array2D = /** @class */ (function () {
1286
1593
  }());
1287
1594
 
1288
1595
  /**
1596
+ * A `Network` allows {@linkcode Agent}s to be connected to each other.
1289
1597
  * @since 0.1.3
1290
1598
  */
1291
1599
  var Network = /** @class */ (function () {
1292
1600
  function Network() {
1601
+ /** @hidden */
1293
1602
  this.adjacencyList = new Map();
1294
- // instantiated and updated in _resetAdjacencyMatrix
1603
+ /**
1604
+ * instantiated and updated in _resetAdjacencyMatrix
1605
+ * @hidden
1606
+ */
1295
1607
  this.adjacencyMatrix = null;
1296
1608
  /**
1297
- * list (JS array) of all the agents
1298
- * in the order they were added to the graph
1609
+ * An array of the {@linkcode Agent}s in this `Network`
1610
+ * (in the order they were added).
1299
1611
  */
1300
1612
  this.agents = [];
1301
1613
  }
1302
1614
  /**
1303
1615
  * Add an agent to the network.
1304
- * Returns `true` if the agent was successfully added.
1305
- * Returns `false` if the agent was already in the network.
1306
- * @param {Agent} agent
1616
+ * @returns Returns `true` if the `Agent` was successfully added, `false` otherwise.
1617
+ *
1618
+ * ```js
1619
+ * const a = new Agent();
1620
+ * network.addAgent(a); // returns true
1621
+ * network.addAgent(a); // returns false since `a` was already in the `Network`
1622
+ * ```
1307
1623
  * @since 0.1.3
1308
1624
  */
1309
1625
  Network.prototype.addAgent = function (agent) {
@@ -1316,8 +1632,8 @@ var Network = /** @class */ (function () {
1316
1632
  return false;
1317
1633
  };
1318
1634
  /**
1319
- * Add all agents in an environment to this network.
1320
- * @param {Environment} environment
1635
+ * Given an {@linkcode Environment}, add all the {@linkcode Agent}s in that `Environment`
1636
+ * to this `Network`. (This is a shortcut for calling `environment.getAgents().forEach(a => network.addAgent(a)));`)
1321
1637
  * @since 0.2.1
1322
1638
  */
1323
1639
  Network.prototype.addFromEnvironment = function (environment) {
@@ -1325,10 +1641,20 @@ var Network = /** @class */ (function () {
1325
1641
  environment.getAgents().forEach(function (agent) { return _this.addAgent(agent); });
1326
1642
  };
1327
1643
  /**
1328
- * Remove an agent from the network.
1329
- * Returns `true` if the agent was successfully removed.
1644
+ * Removes an {@linkcode Agent} from the `Network`.
1645
+ *
1646
+ * ```js
1647
+ * const a = new Agent();
1648
+ * network.addAgent(a);
1649
+ *
1650
+ * network.removeAgent(a); // returns true
1651
+ *
1652
+ * network.removeAgent(a); // returns false since `a` was no longer in the `Network`
1653
+ * ```
1654
+ *
1655
+ * @returns Returns `true` if the agent was successfully removed.
1656
+ *
1330
1657
  * Returns `false` if the agent was not in the network to begin with.
1331
- * @param {Agent} agent
1332
1658
  * @since 0.1.3
1333
1659
  */
1334
1660
  Network.prototype.removeAgent = function (agent) {
@@ -1348,7 +1674,17 @@ var Network = /** @class */ (function () {
1348
1674
  return true;
1349
1675
  };
1350
1676
  /**
1351
- * Removes all agents from the network.
1677
+ * Removes all {@linkcode Agent}s from the `Network`.
1678
+ *
1679
+ * ```js
1680
+ * const network = new Network();
1681
+ * network.addAgent(new Agent());
1682
+ * network.size(); // returns 1
1683
+ *
1684
+ * network.clear();
1685
+ * network.size(); // returns 0
1686
+ * ```
1687
+ *
1352
1688
  * @since 0.2.1
1353
1689
  */
1354
1690
  Network.prototype.clear = function () {
@@ -1358,23 +1694,36 @@ var Network = /** @class */ (function () {
1358
1694
  }
1359
1695
  };
1360
1696
  /**
1361
- * Returns true if successfully connected the two agents, false otherwise
1362
- * (for example, if tried to add an edge between an agent + itself
1363
- * or if the connection already exists).
1364
- * @param {*} a1
1365
- * @param {*} a2
1697
+ * Attempts to create a connection between {@linkcode Agent}s `a` and `b`.
1698
+ * @returns Returns `true` if the connection was successfully created (i.e. if `a` and `b` were previously not connected and now are).
1699
+ *
1700
+ * ```js
1701
+ * const a = new Agent();
1702
+ * const b = new Agent();
1703
+ * network.addAgent(a);
1704
+ * network.addAgent(b);
1705
+ *
1706
+ * network.connect(a, b); // returns true
1707
+ *
1708
+ * network.connect(a, b); // returns false since they are now already connected
1709
+ *
1710
+ * const c = new Agent();
1711
+ * network.connect(a, c); // returns false since `c` is not in the `Network`
1712
+ * ```
1713
+ *
1714
+ * Returns `false` otherwise, for example if `a` and `b` are the same `Agent`, or if either is not in the `Network`.
1366
1715
  * @since 0.1.3
1367
1716
  */
1368
- Network.prototype.connect = function (a1, a2) {
1369
- if (a1 === a2)
1717
+ Network.prototype.connect = function (a, b) {
1718
+ if (a === b)
1370
1719
  return false;
1371
- if (!this.isInNetwork(a1) || !this.isInNetwork(a2))
1720
+ if (!this.isInNetwork(a) || !this.isInNetwork(b))
1372
1721
  return false;
1373
- if (!this.areConnected(a1, a2)) {
1374
- this.adjacencyList.get(a1).push(a2);
1375
- this.adjacencyList.get(a2).push(a1);
1376
- var i1 = this.indexOf(a1);
1377
- var i2 = this.indexOf(a2);
1722
+ if (!this.areConnected(a, b)) {
1723
+ this.adjacencyList.get(a).push(b);
1724
+ this.adjacencyList.get(b).push(a);
1725
+ var i1 = this.indexOf(a);
1726
+ var i2 = this.indexOf(b);
1378
1727
  this.adjacencyMatrix.set(i1, i2, 1);
1379
1728
  this.adjacencyMatrix.set(i2, i1, 1);
1380
1729
  return true;
@@ -1382,24 +1731,42 @@ var Network = /** @class */ (function () {
1382
1731
  return false;
1383
1732
  };
1384
1733
  /**
1385
- * Returns `true` if the given agents are connected in the network.
1386
- * @param {Agent} a1
1387
- * @param {Agent} a2
1734
+ * @returns Returns `true` if {@linkcode Agent}s `a` and `b` are connected, `false` if they are not.
1735
+ *
1736
+ * ```js
1737
+ * network.connect(a, b);
1738
+ * network.areConnected(a, b); // returns true since they have been connected
1739
+ *
1740
+ * network.disconnect(a, b);
1741
+ * network.areConnected(a, b); // returns false since they have been disconnected
1742
+ * ```
1743
+ *
1388
1744
  * @since 0.1.3
1389
1745
  */
1390
- Network.prototype.areConnected = function (a1, a2) {
1391
- if (!this.isInNetwork(a1) || !this.isInNetwork(a2))
1746
+ Network.prototype.areConnected = function (a, b) {
1747
+ if (!this.isInNetwork(a) || !this.isInNetwork(b))
1392
1748
  return false;
1393
- var i1 = this.indexOf(a1);
1394
- var i2 = this.indexOf(a2);
1749
+ var i1 = this.indexOf(a);
1750
+ var i2 = this.indexOf(b);
1395
1751
  return (this.adjacencyMatrix.get(i1, i2) === 1 &&
1396
1752
  this.adjacencyMatrix.get(i2, i1) === 1);
1397
1753
  };
1398
1754
  /**
1399
- * Like with connect, returns `true` if the edge was successfully
1400
- * removed, false if otherwise (if edge did not exist in the first place).
1401
- * @param {agent} a1
1402
- * @param {agent} a2
1755
+ * Attempts to sever the connection between {@linkcode Agent}s `a` and `b`.
1756
+ * @returns Returns `true` if the `Agent`s were successfully disconnected, `false` otherwise.
1757
+ *
1758
+ * ```js
1759
+ * const a = new Agent();
1760
+ * const b = new Agent();
1761
+ * network.addAgent(a);
1762
+ * network.addAgent(b);
1763
+ *
1764
+ * network.connect(a, b);
1765
+ * network.disconnect(a, b); // returns true since they were connected and are no longer
1766
+ *
1767
+ * network.disconnect(a, b); // returns false since they were already not connected
1768
+ * ```
1769
+ *
1403
1770
  * @since 0.1.3
1404
1771
  */
1405
1772
  Network.prototype.disconnect = function (a1, a2) {
@@ -1419,40 +1786,50 @@ var Network = /** @class */ (function () {
1419
1786
  return false;
1420
1787
  };
1421
1788
  /**
1422
- * Number of agents in the network.
1789
+ * @returns Returns the number of {@linkcode Agent}s in the `Network`.
1790
+ *
1791
+ * ```js
1792
+ * const a = new Agent();
1793
+ * const b = new Agent();
1794
+ * const c = new Agent();
1795
+ * [a, b, c].forEach(agt => network.addAgent(agt));
1796
+ *
1797
+ * network.size(); // returns 3
1798
+ * ```
1799
+ *
1423
1800
  * @since 0.1.3
1424
1801
  */
1425
1802
  Network.prototype.size = function () {
1426
1803
  return this.agents.length;
1427
1804
  };
1428
1805
  /**
1429
- * Given a callback function, loop over all the agents in the network
1430
- * and invoke the callback, passing the agent + its index as parameters.
1431
- * @param {Function} cb
1806
+ * Loop over all the {@linkcode Agent}s in the `Network` (in the order they were added),
1807
+ * and invoke the `callback` function with the `Agent` and an index passed as parameters.
1432
1808
  * @since 0.1.3
1433
1809
  */
1434
- Network.prototype.forEach = function (cb) {
1435
- this.agents.forEach(cb);
1810
+ Network.prototype.forEach = function (callback) {
1811
+ this.agents.forEach(callback);
1436
1812
  };
1437
1813
  /**
1438
- * Same as forEach, but in random order.
1439
- * @param {Function} cb
1814
+ * The same method as {@linkcode forEach}, but executes in random order.
1440
1815
  * @since 0.1.3
1441
1816
  */
1442
- Network.prototype.forEachRand = function (cb) {
1443
- shuffle(this.agents).forEach(cb);
1817
+ Network.prototype.forEachRand = function (callback) {
1818
+ shuffle(this.agents).forEach(callback);
1444
1819
  };
1445
1820
  /**
1446
- * Returns true if the agent is in the network, false if it is not.
1447
- * @param {Agent} agent
1821
+ * Returns `true` if the given {@linkcode Agent} is in the `Network`, `false` if it is not.
1448
1822
  * @since 0.1.3
1449
1823
  */
1450
1824
  Network.prototype.isInNetwork = function (agent) {
1451
1825
  return this.adjacencyList.has(agent);
1452
1826
  };
1453
1827
  /**
1454
- * Get the agent at index i.
1455
- * @param {number} i
1828
+ * Returns the {@linkcode Agent} at index `i`, where `i = 0` is the first `Agent`
1829
+ * added to the `Network`, `i = 1` the second, etc.
1830
+ *
1831
+ * Negative indices are allowed, so `network.get(-1)` returns the `Agent` that was most recently
1832
+ * added to the `Network`, `-2` the second-most recent, etc.
1456
1833
  * @since 0.1.3
1457
1834
  */
1458
1835
  Network.prototype.get = function (i) {
@@ -1463,17 +1840,26 @@ var Network = /** @class */ (function () {
1463
1840
  return this.agents[i];
1464
1841
  };
1465
1842
  /**
1466
- * Get the index of a given agent.
1467
- * @param {Agent} agent
1843
+ * Returns the index of the given {@linkcode Agent} in the {@linkcode agents} array.
1468
1844
  * @since 0.1.3
1469
1845
  */
1470
1846
  Network.prototype.indexOf = function (agent) {
1471
1847
  return this.agents.indexOf(agent);
1472
1848
  };
1473
1849
  /**
1474
- * Return the agents that are neighbors of a given agent
1475
- * (in a JS array). If the agent is not in the network, returns `null`.
1476
- * @param {Agent} agent
1850
+ * Returns an array of {@linkcode Agent}s that are connected to the given `Agent` (in no guaranteed order).
1851
+ *
1852
+ * Returns `null` if the given `Agent` is not in the `Network`.
1853
+ *
1854
+ * ```js
1855
+ * // suppose a, b, and c are connected
1856
+ * network.neighbors(a); // returns [b, c] (or [c, b])
1857
+ *
1858
+ * network.disconnect(a, c);
1859
+ * network.neighbors(a); // returns [b]
1860
+ * network.neighbors(c); // returns [b]
1861
+ * ```
1862
+ *
1477
1863
  * @since 0.1.3
1478
1864
  */
1479
1865
  Network.prototype.neighbors = function (agent) {
@@ -1482,7 +1868,7 @@ var Network = /** @class */ (function () {
1482
1868
  return this.adjacencyList.get(agent);
1483
1869
  };
1484
1870
  /**
1485
- * Connect every agent in the network to every other agent.
1871
+ * Draw a connection between every pair of {@linkcode Agent}s in the `Network`.
1486
1872
  * @since 0.1.3
1487
1873
  */
1488
1874
  Network.prototype.complete = function () {
@@ -1495,6 +1881,7 @@ var Network = /** @class */ (function () {
1495
1881
  /**
1496
1882
  * Internal helper function to reset the adjacencyMatrix.
1497
1883
  * This gets called when agents are added to or removed from the network.
1884
+ * @hidden
1498
1885
  */
1499
1886
  Network.prototype._resetAdjacencyMatrix = function () {
1500
1887
  var size = this.size();
@@ -1511,11 +1898,7 @@ var Network = /** @class */ (function () {
1511
1898
  this.adjacencyMatrix = newMatrix;
1512
1899
  };
1513
1900
  /**
1514
- * Returns `true` if a, b, and c are a 'triplet' of agents --
1515
- * if (at least) one of the three is connected to the other two.
1516
- * @param {Agent} a
1517
- * @param {Agent} b
1518
- * @param {Agent} c
1901
+ * Returns `true` if `Agent`s a, b, and c form a 'triplet' &mdash; if (at least) one of the three is connected to the other two. Returns `false` otherwise.
1519
1902
  * @since 0.5.17
1520
1903
  */
1521
1904
  Network.prototype.isTriplet = function (a, b, c) {
@@ -1529,11 +1912,7 @@ var Network = /** @class */ (function () {
1529
1912
  return connections >= 2;
1530
1913
  };
1531
1914
  /**
1532
- * Returns `true` if a, b, and c are a 'closed triplet' of agents --
1533
- * each connected to the other two.
1534
- * @param {Agent} a
1535
- * @param {Agent} b
1536
- * @param {Agent} c
1915
+ * Returns `true` if `Agent`s a, b, and c form a 'closed triplet' &mdash; if each of the three are connected to the other two. Returns `false` otherwise.
1537
1916
  * @since 0.5.17
1538
1917
  */
1539
1918
  Network.prototype.isClosedTriplet = function (a, b, c) {
@@ -1546,6 +1925,7 @@ var Network = /** @class */ (function () {
1546
1925
  ].filter(function (v) { return v; }).length;
1547
1926
  return connections === 3;
1548
1927
  };
1928
+ /** @hidden */
1549
1929
  Network.prototype._globalClusteringCoefficient = function () {
1550
1930
  var _this = this;
1551
1931
  var triplets = 0;
@@ -1567,12 +1947,15 @@ var Network = /** @class */ (function () {
1567
1947
  return closedTriplets / triplets;
1568
1948
  };
1569
1949
  /**
1570
- * If an agent is passed as the single parameter, returns the local
1571
- * clustering coefficient for that agent (a measure of how connected that
1572
- * agent's neighbors are to each other).
1573
- * If no parameter is passed, returns the global clustering coefficient
1574
- * of the network (an aggregate measure of how connected are the agents).
1575
- * @param {Agent} [agent]
1950
+ * The {@link https://en.wikipedia.org/wiki/Clustering_coefficient | clustering coefficient} is a measure of how
1951
+ * closely connected either an individual {@linkcode Agent}'s connections are or the `Network` as a whole is.
1952
+ *
1953
+ * If an `Agent` is passed as the single parameter, returns the {@link https://en.wikipedia.org/wiki/Clustering_coefficient#Local_clustering_coefficient | local
1954
+ * clustering coefficient} for that `Agent`.
1955
+ *
1956
+ * If no parameter is passed, returns the {@link https://en.wikipedia.org/wiki/Clustering_coefficient#Global_clustering_coefficient | global clustering coefficient}
1957
+ * of the `Network` (an aggregate measure of how connected the `Agent`s are).
1958
+ *
1576
1959
  * @since 0.5.17
1577
1960
  */
1578
1961
  Network.prototype.clusteringCoefficient = function (agent) {
@@ -1596,9 +1979,11 @@ var Network = /** @class */ (function () {
1596
1979
  return (2 * clusterConnections) / (k * (k - 1));
1597
1980
  };
1598
1981
  /**
1599
- * Returns the average clustering coefficient for the network (the average
1600
- * of the local clustering coefficient across all agents). Note that
1601
- * this is a different measurement from the _global_ clustering coefficient.
1982
+ * Returns the {@link https://en.wikipedia.org/wiki/Clustering_coefficient#Network_average_clustering_coefficient | average clustering coefficient} for the `Network` (the average
1983
+ * of the {@link Network.clusteringCoefficient | local clustering coefficient} across all `Agent`s).
1984
+ *
1985
+ * Note that this is a different measurement from the _global_ clustering coefficient
1986
+ * (i.e. calling {@linkcode clusteringCoefficient} without any parameters).
1602
1987
  * @since 0.5.17
1603
1988
  */
1604
1989
  Network.prototype.averageClusteringCoefficient = function () {
@@ -1654,6 +2039,14 @@ var BBox = /** @class */ (function () {
1654
2039
  }());
1655
2040
 
1656
2041
  /**
2042
+ * Return the minimum value from an array of numbers.
2043
+ *
2044
+ * ```js
2045
+ * min([1, 2, 3]); // returns 1
2046
+ * min([10]); // returns 10
2047
+ *
2048
+ * min([]); // returns null for empty arrays
2049
+ * ```
1657
2050
  * @since 0.2.0
1658
2051
  */
1659
2052
  function min(arr) {
@@ -1663,6 +2056,15 @@ function min(arr) {
1663
2056
  }
1664
2057
 
1665
2058
  /**
2059
+ * Return the maximum value from an array of numbers.
2060
+ *
2061
+ * ```js
2062
+ * max([1, 2, 3]); // returns 3
2063
+ * max([10]); // returns 10
2064
+ *
2065
+ * max([]); // returns null for empty arrays
2066
+ * ```
2067
+ *
1666
2068
  * @since 0.2.0
1667
2069
  */
1668
2070
  function max(arr) {
@@ -1704,8 +2106,16 @@ function percentile(arr, n) {
1704
2106
  }
1705
2107
 
1706
2108
  /**
1707
- * Find the median value of an array of numbers. If there are an even number
1708
- * of elements in the array, takes the mean of the two values closest to the median.
2109
+ * Return the mean value from an array of numbers.
2110
+ *
2111
+ * ```js
2112
+ * median([1, 2, 3]); // returns 2
2113
+ * median([10]); // returns 10
2114
+ * median([1, 2, 3, 4]); // returns 2.5 (the mean of the two median values)
2115
+ *
2116
+ * median([]); // returns null for empty arrays
2117
+ * ```
2118
+ *
1709
2119
  * @param {number[]} arr
1710
2120
  * @since 0.2.0
1711
2121
  */
@@ -1713,6 +2123,9 @@ function median(arr) {
1713
2123
  return percentile(arr, 0.5);
1714
2124
  }
1715
2125
 
2126
+ function isMultipleSampleFunc(f) {
2127
+ return f([1]).length > 0;
2128
+ }
1716
2129
  var sample;
1717
2130
  /**
1718
2131
  * Gets a random element from `array`.
@@ -1802,12 +2215,21 @@ function sampler(n) {
1802
2215
 
1803
2216
  /// <reference path="../types/Point.d.ts" />
1804
2217
  /**
1805
- * Finds the distance between `p1` and `p2`. The inputs may be plain objects
1806
- * with `x`, `y`, and/or `z` keys, or Agent-like objects who have
1807
- * `x`, `y`, and/or `z` data.
1808
- * @param {Point|Agent} p1
1809
- * @param {Point|Agent} p2
1810
- * @return {number} The distance between p1 and p2.
2218
+ * Finds the distance between `p1` and `p2`.
2219
+ *
2220
+ * The inputs may be plain objects with `x`, `y`, and/or `z` keys, {@linkcode Vector}s,
2221
+ * or {@linkcode Agent}s with `x`, `y`, and/or `z` data.
2222
+ *
2223
+ * ```js
2224
+ * const a1 = new Agent();
2225
+ * const a2 = new Agent({ x: 3, y: 4 });
2226
+ * distance(a1, a2); // returns 5 (defaults to x = 0 and y = 0 for a1)
2227
+ *
2228
+ * const p1 = { x: 0, y: 2 };
2229
+ * const p2 = { x: 0, y: 4 };
2230
+ * distance(p1, p2); // returns 2
2231
+ * ```
2232
+ *
1811
2233
  * @since 0.0.10
1812
2234
  */
1813
2235
  function distance(p1, p2) {
@@ -2105,6 +2527,14 @@ var KDTree = /** @class */ (function () {
2105
2527
  }());
2106
2528
 
2107
2529
  /**
2530
+ * Finds the {@link https://en.wikipedia.org/wiki/Greatest_common_divisor | greatest common divisor} of `a` and `b`.
2531
+ *
2532
+ * ```js
2533
+ * gcd(7, 13); // returns 1
2534
+ * gcd(9, 15); // returns 3
2535
+ * gcd(12, 24); // returns 12
2536
+ * ```
2537
+ *
2108
2538
  * @since 0.4.5
2109
2539
  */
2110
2540
  function gcd(a, b) {
@@ -2173,32 +2603,80 @@ var defaultTerrainOptions = {
2173
2603
  grayscale: false,
2174
2604
  scale: 1
2175
2605
  };
2606
+ var BLACK = { r: 0, g: 0, b: 0, a: 255 };
2607
+ var WHITE = { r: 255, g: 255, b: 255, a: 255 };
2608
+ var RED = { r: 255, g: 0, b: 0, a: 255 };
2609
+ var MAROON = { r: 127, g: 0, b: 0, a: 255 };
2610
+ var YELLOW = { r: 255, g: 255, b: 0, a: 255 };
2611
+ var BLUE = { r: 0, g: 0, b: 255, a: 255 };
2612
+ var GREEN = { r: 0, g: 127, b: 0, a: 255 };
2613
+ var LIME = { r: 0, g: 255, b: 0, a: 255 };
2614
+ var AQUA = { r: 0, g: 255, b: 255, a: 255 };
2615
+ var ORANGE = { r: 255, g: 165, b: 0, a: 255 };
2616
+ var FUCHSIA = { r: 255, g: 0, b: 255, a: 255 };
2617
+ var PURPLE = { r: 127, g: 0, b: 127, a: 255 };
2176
2618
  /**
2619
+ * Each static member of the `Colors` class (e.g. `Colors.GREEN`, `Colors.RED`) is a pixel-like object with `r`, `g`, `b`, and `a` values that range from `0` to `255`.
2177
2620
  * @since 0.4.0
2178
2621
  */
2179
- var Colors = {
2180
- BLACK: { r: 0, g: 0, b: 0, a: 255 },
2181
- WHITE: { r: 255, g: 255, b: 255, a: 255 },
2182
- RED: { r: 255, g: 0, b: 0, a: 255 },
2183
- MAROON: { r: 127, g: 0, b: 0, a: 255 },
2184
- YELLOW: { r: 255, g: 255, b: 0, a: 255 },
2185
- BLUE: { r: 0, g: 0, b: 255, a: 255 },
2186
- GREEN: { r: 0, g: 127, b: 0, a: 255 },
2187
- LIME: { r: 0, g: 255, b: 0, a: 255 },
2188
- AQUA: { r: 0, g: 255, b: 255, a: 255 },
2189
- ORANGE: { r: 255, g: 165, b: 0, a: 255 },
2190
- FUCHSIA: { r: 255, g: 0, b: 255, a: 255 },
2191
- PURPLE: { r: 127, g: 0, b: 127, a: 255 }
2192
- };
2622
+ var Colors = /** @class */ (function () {
2623
+ function Colors() {
2624
+ }
2625
+ /** <div style="width: 100%; height: 20px; background-color: rgb(0, 0, 0);"></div> */
2626
+ Colors.BLACK = BLACK;
2627
+ /** <div style="width: 100%; height: 20px; background-color: rgb(255, 255, 255); border: 1px solid #eee;"></div> */
2628
+ Colors.WHITE = WHITE;
2629
+ /** <div style="width: 100%; height: 20px; background-color: rgb(255, 0, 0);"></div> */
2630
+ Colors.RED = RED;
2631
+ /** <div style="width: 100%; height: 20px; background-color: rgb(127, 0, 0);"></div> */
2632
+ Colors.MAROON = MAROON;
2633
+ /** <div style="width: 100%; height: 20px; background-color: rgb(255,255, 0);"></div> */
2634
+ Colors.YELLOW = YELLOW;
2635
+ /** <div style="width: 100%; height: 20px; background-color: rgb(0, 0, 255);"></div> */
2636
+ Colors.BLUE = BLUE;
2637
+ /** <div style="width: 100%; height: 20px; background-color: rgb(0, 127, 0);"></div> */
2638
+ Colors.GREEN = GREEN;
2639
+ /** <div style="width: 100%; height: 20px; background-color: rgb(0, 255, 0);"></div> */
2640
+ Colors.LIME = LIME;
2641
+ /** <div style="width: 100%; height: 20px; background-color: rgb(0, 255, 255);"></div> */
2642
+ Colors.AQUA = AQUA;
2643
+ /** <div style="width: 100%; height: 20px; background-color: rgb(255, 165, 0);"></div> */
2644
+ Colors.ORANGE = ORANGE;
2645
+ /** <div style="width: 100%; height: 20px; background-color: rgb(255, 0, 255);"></div> */
2646
+ Colors.FUCHSIA = FUCHSIA;
2647
+ /** <div style="width: 100%; height: 20px; background-color: rgb(127, 0, 127);"></div> */
2648
+ Colors.PURPLE = PURPLE;
2649
+ return Colors;
2650
+ }());
2193
2651
  /**
2652
+ * The `Terrain` class lets {@linkcode Environment}s function as lattices upon which {@link https://en.wikipedia.org/wiki/Cellular_automaton | cellular automata} can grow. With a `Terrain`, {@linkcode Agent}s may not be necessary, since all the cells of a `Terrain` can follow update rules (similar to but simplified from `Agent`s).
2653
+ *
2654
+ * ### Usage
2655
+ *
2656
+ * ```js
2657
+ * const environment = new Environment();
2658
+ * const terrain = new Terrain(30, 30); // create a 30 x 30 Terrain
2659
+ * environment.use(terrain); // tell the Environment to 'use' this Terrain as a helper
2660
+ * ```
2661
+ *
2194
2662
  * @since 0.4.0
2195
2663
  */
2196
2664
  var Terrain = /** @class */ (function () {
2197
2665
  /**
2666
+ * Instantiate a new `Terrain` by passing its `width` and `height` as the first two parameters, and an optional configuration object as the third.
2667
+ *
2668
+ * ### Options
2669
+ *
2670
+ * - `async` (*boolean* = `false`) &mdash; Whether to run the `Terrain` in synchronous (`true`) or asynchronous (`mode`). Defaults to synchronous. Depending on the timing mode, {@link addRule | Terrain update rules} should be written differently.
2671
+ * - `grayscale` (*boolean* = `false`)
2672
+ * - In **color mode** (the default), each cell of a `Terrain` is represented by a {@link Colors | pixel-like object} (an object with numeric keys `r`, `g`, `b`, and `a` ranging from 0-255).
2673
+ * - In **grayscale mode**, each cell of a `Terrain` is represented by a single number ranging from 0 (black) to 255 (white).
2674
+ * - `scale` (*number* = `1`) &mdash; The size, in pixels, of each cell's width and height when the `Terrain` is rendered using a {@linkcode CanvasRenderer}. In the below screenshots, the `Terrain` on the left uses a scale of `1` while the one on the right uses a scale of `5`:
2198
2675
  *
2199
- * @param {number} width - The width of the terrain
2200
- * @param {number} height - The height of the terrain
2201
- * @param options
2676
+ * <img alt="Terrain with scale = 1" style="width: 49%;" src="https://cms.flocc.network/wp-content/uploads/2020/04/terrain-1.png">
2677
+ * <img alt="Terrain with scale = 5" style="width: 49%;" src="https://cms.flocc.network/wp-content/uploads/2020/04/terrain-5.png">
2678
+ *
2679
+ * In addition to the above setup, you will need to {@link init | initialize} the `Terrain` and {@link addRule | add an update rule}.
2202
2680
  */
2203
2681
  function Terrain(width, height, options) {
2204
2682
  if (options === void 0) { options = defaultTerrainOptions; }
@@ -2218,9 +2696,16 @@ var Terrain = /** @class */ (function () {
2218
2696
  this.nextData = new Uint8ClampedArray(this.data);
2219
2697
  }
2220
2698
  /**
2221
- * Initialize (or overwrite) the terrain data by passing a function with parameters (x, y)
2222
- * and returning a pixel value.
2223
- * @param {Function} rule - The rule to follow to instantiate pixel values
2699
+ * Initialize (or overwrite) all cell values. The rule you pass has the same signature
2700
+ * as {@linkcode addRule}, but should always return a value (either a number or {@linkcode Colors | pixel-like object}).
2701
+ *
2702
+ * ```js
2703
+ * // initializes cells randomly to either blue or red
2704
+ * terrain.init((x, y) => {
2705
+ * return utils.uniform() > 0.5 ? Colors.BLUE : Colors.RED;
2706
+ * });
2707
+ * ```
2708
+ *
2224
2709
  * @since 0.4.0
2225
2710
  */
2226
2711
  Terrain.prototype.init = function (rule) {
@@ -2243,12 +2728,41 @@ var Terrain = /** @class */ (function () {
2243
2728
  }
2244
2729
  }
2245
2730
  }
2731
+ this.nextData = new Uint8ClampedArray(this.data);
2246
2732
  };
2247
2733
  /**
2248
- * Like with agents, this adds an update rule for the terrain. The function
2249
- * passed as the rule should be called with the parameters (x, y), and should return
2250
- * a pixel-like object { r: number, g: number, b: number, a: number } or number.
2251
- * @param {Function} rule - The update rule to be called on environment.tick()
2734
+ * Similar to adding behavior to {@linkcode Agent}s, this adds an update rule for the `Terrain`.
2735
+ * The function passed as the rule should be called with the parameters (`x`, `y`). In synchronous mode,
2736
+ * it should return a value that is the color of that cell on the next time step.
2737
+ *
2738
+ * ```js
2739
+ * // turns a cell red if the x-value is greater than 200,
2740
+ * // blue if the x-value is less than 100,
2741
+ * // and leaves it unchanged in between
2742
+ * terrain.addRule((x, y) => {
2743
+ * if (x > 200) {
2744
+ * return Colors.RED;
2745
+ * } else if (x < 100) {
2746
+ * return Colors.BLUE;
2747
+ * }
2748
+ * });
2749
+ * ```
2750
+ *
2751
+ * For grayscale mode, functions passed to `addRule` should return a number instead of a {@linkcode Colors | pixel-like object}.
2752
+ *
2753
+ * In asynchronous mode, functions should use the {@linkcode set} method to update either this cell
2754
+ * or a different cell.
2755
+ *
2756
+ * ```js
2757
+ * // swaps the colors of this cell and the one five cells to the right
2758
+ * terrain.addRule((x, y) => {
2759
+ * const here = terrain.sample(x, y);
2760
+ * const there = terrain.sample(x + 5, y);
2761
+ * terrain.set(x, y, there);
2762
+ * terrain.set(x + 5, y, here);
2763
+ * });
2764
+ * ```
2765
+ *
2252
2766
  * @since 0.4.0
2253
2767
  */
2254
2768
  Terrain.prototype.addRule = function (rule) {
@@ -2256,14 +2770,23 @@ var Terrain = /** @class */ (function () {
2256
2770
  };
2257
2771
  /**
2258
2772
  * Given a local path or remote URL to an image, load that image and set
2259
- * terrain pixel data accordingly. This will scale the image to match the
2260
- * dimensionss of the terrain.
2773
+ * `Terrain` data accordingly. This will scale the image to match the
2774
+ * dimensions of the terrain.
2775
+ *
2261
2776
  * A 2nd callback parameter fires once the image has been successfully loaded.
2262
- * @param {string} path - The path or URL to the image
2263
- * @param {Function} cb - The function to call once the image loads
2777
+ *
2778
+ * ```js
2779
+ * const terrain = new Terrain(400, 400);
2780
+ * terrain.load("/path/to/local/image.jpg", function() {
2781
+ * console.log("Image loaded successfully!");
2782
+ * });
2783
+ * ```
2784
+ *
2785
+ * @param {string} path - The path to or URL of the image
2786
+ * @param {Function} cb - The function to call once the image loads (takes no parameters)
2264
2787
  * @since 0.4.0
2265
2788
  */
2266
- Terrain.prototype.load = function (path, cb) {
2789
+ Terrain.prototype.load = function (path, callback) {
2267
2790
  var _this = this;
2268
2791
  var img = document.createElement("img");
2269
2792
  img.src = path;
@@ -2277,8 +2800,8 @@ var Terrain = /** @class */ (function () {
2277
2800
  .getContext("2d")
2278
2801
  .getImageData(0, 0, _this.width, _this.height).data;
2279
2802
  _this.data = data;
2280
- if (cb)
2281
- cb();
2803
+ if (callback)
2804
+ callback();
2282
2805
  };
2283
2806
  img.onerror = function () {
2284
2807
  console.error("There was an error loading the image for the terrain. Check the path to the URL to make sure that it exists, \n or consider saving a local copy to pull from the same origin: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors");
@@ -2319,16 +2842,21 @@ var Terrain = /** @class */ (function () {
2319
2842
  }
2320
2843
  };
2321
2844
  /**
2322
- * Get the neighbors of a coordinate within a certain radius.
2323
- * Depending on the fourth parameter, retrieves either the von Neumann neighborhood
2324
- * (https://en.wikipedia.org/wiki/Von_Neumann_neighborhood) or the Moore neighborhood
2325
- * (https://en.wikipedia.org/wiki/Moore_neighborhood).
2845
+ * Get the values of the neighbors of a cell within a certain radius.
2846
+ * Depending on the fourth parameter, retrieves either the {@link https://en.wikipedia.org/wiki/Von_Neumann_neighborhood | von Neumann neighborhood}
2847
+ * or the {@link https://en.wikipedia.org/wiki/Moore_neighborhood | Moore neighborhood}.
2326
2848
  *
2327
- * @param {number} x - The x coordinate
2328
- * @param {number} y - The y coordinate
2329
- * @param {number} radius - how far to look for neighbors
2330
- * @param {boolean} moore - whether to use the Moore neighborhood or von Neumann (defaults to von Neumann)
2331
- * @returns {Pixel[] | number[]} - An array of numbers (grayscale only) or pixel-like objects
2849
+ * ```js
2850
+ * // in grayscale mode:
2851
+ * terrain.neighbors(5, 5, 1); // returns [127, 100, 255, 255] (4 values)
2852
+ *
2853
+ * // in color mode:
2854
+ * terrain.neighbors(5, 5, 1, true);
2855
+ * // returns [{ r: 255, g: 0, b: 0, a: 255 }, { r: 127, ... }, ...] (8 values)
2856
+ * ```
2857
+ *
2858
+ * @param moore - Defaults to using the von Neumann neighborhood.
2859
+ * @returns Either an array of numbers (grayscale mode) or {@link Colors | pixel-like objects} (color mode).
2332
2860
  * @since 0.4.0
2333
2861
  */
2334
2862
  Terrain.prototype.neighbors = function (x, y, radius, moore) {
@@ -2350,6 +2878,7 @@ var Terrain = /** @class */ (function () {
2350
2878
  }
2351
2879
  return neighbors;
2352
2880
  };
2881
+ /** @hidden */
2353
2882
  Terrain.prototype._setAbstract = function (data, x, y, r, g, b, a) {
2354
2883
  var _a = this, width = _a.width, height = _a.height, opts = _a.opts;
2355
2884
  var grayscale = opts.grayscale, scale = opts.scale;
@@ -2402,9 +2931,11 @@ var Terrain = /** @class */ (function () {
2402
2931
  Terrain.prototype.set = function (x, y, r, g, b, a) {
2403
2932
  this._setAbstract(this.data, x, y, r, g, b, a);
2404
2933
  };
2934
+ /** @hidden */
2405
2935
  Terrain.prototype._setNext = function (x, y, r, g, b, a) {
2406
2936
  this._setAbstract(this.nextData, x, y, r, g, b, a);
2407
2937
  };
2938
+ /** @hidden */
2408
2939
  Terrain.prototype._execute = function (x, y) {
2409
2940
  var _a = this, rule = _a.rule, opts = _a.opts;
2410
2941
  var async = opts.async;
@@ -2417,6 +2948,7 @@ var Terrain = /** @class */ (function () {
2417
2948
  // update on nextData
2418
2949
  this._setNext(x, y, result);
2419
2950
  };
2951
+ /** @hidden */
2420
2952
  Terrain.prototype._loop = function (_a) {
2421
2953
  var _b = _a.randomizeOrder, randomizeOrder = _b === void 0 ? false : _b;
2422
2954
  var _c = this, rule = _c.rule, width = _c.width, height = _c.height, opts = _c.opts;
@@ -2446,52 +2978,272 @@ var Terrain = /** @class */ (function () {
2446
2978
  return Terrain;
2447
2979
  }());
2448
2980
 
2449
- var defaultTickOptions = {
2450
- activation: "uniform",
2451
- count: 1,
2452
- randomizeOrder: false
2453
- };
2454
- var defaultEnvironmentOptions = {
2455
- torus: true,
2456
- height: 0,
2457
- width: 0
2458
- };
2459
- var warnOnce = once(console.warn.bind(console));
2460
2981
  /**
2461
- * An environment provides the space and time in which agents interact.
2462
- * Environments, like agents, can store data in key-value pairs
2463
- * that can be updated over time.
2982
+ * Given a `number` and `min` and `max` values, restrict the number
2983
+ * to the range specified.
2984
+ *
2985
+ * ```js
2986
+ * clamp(5, 1, 10); // returns 5
2987
+ * clamp(5, 2, 4); // returns 4
2988
+ * clamp(0, -4, -3); // returns -3
2989
+ * ```
2990
+ *
2464
2991
  * @since 0.0.5
2465
2992
  */
2466
- var Environment = /** @class */ (function (_super) {
2467
- __extends(Environment, _super);
2468
- function Environment(opts) {
2469
- if (opts === void 0) { opts = defaultEnvironmentOptions; }
2470
- var _this = _super.call(this) || this;
2471
- /** @member {Agent[]} */
2472
- _this.agents = [];
2473
- _this.agentsById = new Map();
2474
- _this.cache = new Map();
2475
- _this.helpers = {
2476
- kdtree: null,
2477
- network: null,
2478
- terrain: null
2479
- };
2480
- /** @member {AbstractRenderer[]} */
2481
- _this.renderers = [];
2482
- /** @since 0.1.4 */
2483
- _this.time = 0;
2484
- _this.opts = Object.assign({}, defaultEnvironmentOptions);
2485
- _this.opts = Object.assign(_this.opts, opts);
2486
- _this.width = _this.opts.width;
2487
- _this.height = _this.opts.height;
2488
- return _this;
2993
+ function clamp(x, min, max) {
2994
+ if (x < min)
2995
+ return min;
2996
+ if (x > max)
2997
+ return max;
2998
+ return x;
2999
+ }
3000
+
3001
+ /**
3002
+ * Given a mean and standard deviation,
3003
+ * returns a value from a normal/Gaussian distribution.
3004
+ *
3005
+ * ```js
3006
+ * // returns values mostly between 5 and 15 (but sometimes lower or higher)
3007
+ * gaussian(10, 5);
3008
+ *
3009
+ * // no parameters defaults to mean = 0, std. dev. = 1
3010
+ * gaussian(); // mostly values between -1 and 1
3011
+ * ```
3012
+ *
3013
+ * @since 0.0.8
3014
+ */
3015
+ function gaussian(mean, sd) {
3016
+ if (mean === void 0) { mean = 0; }
3017
+ if (sd === void 0) { sd = 1; }
3018
+ var y, x1, x2, w;
3019
+ do {
3020
+ x1 = 2 * uniform() - 1;
3021
+ x2 = 2 * uniform() - 1;
3022
+ w = x1 * x1 + x2 * x2;
3023
+ } while (w >= 1);
3024
+ w = Math.sqrt((-2 * Math.log(w)) / w);
3025
+ y = x1 * w;
3026
+ return y * sd + mean;
3027
+ }
3028
+
3029
+ /// <reference path="../types/Point.d.ts" />
3030
+ /**
3031
+ * Finds the {@link https://en.wikipedia.org/wiki/Taxicab_geometry | Manhattan distance} between `p1` and `p2`.
3032
+ *
3033
+ * The inputs may be plain objects with `x`, `y`, and/or `z` keys, {@linkcode Vector}s,
3034
+ * or {@linkcode Agent}s with `x`, `y`, and/or `z` data.
3035
+ *
3036
+ * ```js
3037
+ * const a1 = new Agent();
3038
+ * const a2 = new Agent({ x: 3, y: 4 });
3039
+ * manhattanDistance(a1, a2); // returns 7 (defaults to x = 0 and y = 0 for a1)
3040
+ *
3041
+ * const p1 = { x: 3, y: 2 };
3042
+ * const p2 = { x: 0, y: 4 };
3043
+ * manhattanDistance(p1, p2); // returns 5
3044
+ * ```
3045
+ *
3046
+ * @since 0.0.12
3047
+ */
3048
+ function manhattanDistance(p1, p2) {
3049
+ var x1 = (p1 instanceof Agent ? p1.get("x") : p1.x) || 0;
3050
+ var y1 = (p1 instanceof Agent ? p1.get("y") : p1.y) || 0;
3051
+ var z1 = (p1 instanceof Agent ? p1.get("z") : p1.z) || 0;
3052
+ var x2 = (p2 instanceof Agent ? p2.get("x") : p2.x) || 0;
3053
+ var y2 = (p2 instanceof Agent ? p2.get("y") : p2.y) || 0;
3054
+ var z2 = (p2 instanceof Agent ? p2.get("z") : p2.z) || 0;
3055
+ var dx = Math.abs(x2 - x1);
3056
+ var dy = Math.abs(y2 - y1);
3057
+ var dz = Math.abs(z2 - z1);
3058
+ // distance for toroidal environments
3059
+ if (p1 instanceof Agent &&
3060
+ p2 instanceof Agent &&
3061
+ p1.environment &&
3062
+ p2.environment &&
3063
+ p1.environment === p2.environment &&
3064
+ p1.environment.width &&
3065
+ p1.environment.height &&
3066
+ p1.environment.opts.torus) {
3067
+ var environment = p1.environment;
3068
+ var width = environment.width, height = environment.height;
3069
+ if (dx > width / 2)
3070
+ dx = width - dx;
3071
+ if (dy > height / 2)
3072
+ dy = height - dy;
2489
3073
  }
3074
+ return dx + dy + dz;
3075
+ }
3076
+
3077
+ /**
3078
+ * Maps a number x, from the given domain aMin --> aMax,
3079
+ * onto the given range bMin --> bMax.
3080
+ * Ex: remap(5, 0, 10, 0, 100) => 50.
3081
+ * @param {number} x
3082
+ * @param {number} aMin
3083
+ * @param {number} aMax
3084
+ * @param {number} bMin
3085
+ * @param {number} bMax
3086
+ * @returns {number} The remapped value.
3087
+ * @since 0.0.5
3088
+ */
3089
+ function remap(x, aMin, aMax, bMin, bMax) {
3090
+ return bMin + ((bMax - bMin) * (x - aMin)) / (aMax - aMin);
3091
+ }
3092
+
3093
+ /**
3094
+ * Seed a pseudo-random number generator with a value.
3095
+ * This can be used to produce predictable pseudo-random numbers.
3096
+ * When calling `utils.random`, `utils.sample`, or other functions
3097
+ * relying on randomness with the same initial seed, the values
3098
+ * generated will always be the same.
3099
+ *
3100
+ * Predictable randomness can be turned off by calling `seed(null)`, or reset
3101
+ * by calling `seed(value)` again with the initial value you used.
3102
+ * @param value
3103
+ * @since 0.5.0
3104
+ */
3105
+ var seed = function (value) { return PRNG.seed(value); };
3106
+
3107
+ /**
3108
+ * Find the standard deviation of an Array of numbers.
3109
+ * @param {Array<number>} arr
3110
+ * @returns {number}
3111
+ * @since 0.0.16
3112
+ */
3113
+ function stdDev(arr) {
3114
+ if (arr.length === 0)
3115
+ return null;
3116
+ var ave = mean(arr);
3117
+ return Math.sqrt(mean(arr.map(function (x) { return (x - ave) * (x - ave); })));
3118
+ }
3119
+
3120
+ /**
3121
+ * @since 0.1.4
3122
+ */
3123
+ function zfill(str, width) {
3124
+ if (width === void 0) { width = 0; }
3125
+ var output = str;
3126
+ while (output.length < width)
3127
+ output = "0" + output;
3128
+ return output;
3129
+ }
3130
+
3131
+
3132
+
3133
+ var utils = /*#__PURE__*/Object.freeze({
3134
+ __proto__: null,
3135
+ clamp: clamp,
3136
+ distance: distance,
3137
+ gaussian: gaussian,
3138
+ gcd: gcd,
3139
+ manhattanDistance: manhattanDistance,
3140
+ lerp: lerp,
3141
+ remap: remap,
3142
+ random: random,
3143
+ sample: sample$1,
3144
+ sampler: sampler,
3145
+ seed: seed,
3146
+ series: series,
3147
+ shuffle: shuffle,
3148
+ sum: sum,
3149
+ max: max,
3150
+ mean: mean,
3151
+ median: median,
3152
+ min: min,
3153
+ percentile: percentile,
3154
+ stdDev: stdDev,
3155
+ uniform: uniform,
3156
+ uuid: uuid$1,
3157
+ zfill: zfill
3158
+ });
3159
+
3160
+ var defaultTickOptions = {
3161
+ activation: "uniform",
3162
+ activationCount: 1,
3163
+ count: 1,
3164
+ randomizeOrder: false
3165
+ };
3166
+ var defaultEnvironmentOptions = {
3167
+ torus: true,
3168
+ height: 0,
3169
+ width: 0
3170
+ };
3171
+ var warnOnce = once(console.warn.bind(console));
3172
+ /**
3173
+ * An environment provides the space and time in which Agents interact.
3174
+ * Environments are themselves Agents, and can store data in key-value
3175
+ * pairs that can be manipulated just like Agent data.
3176
+ * @since 0.0.5
3177
+ */
3178
+ var Environment = /** @class */ (function (_super) {
3179
+ __extends(Environment, _super);
2490
3180
  /**
2491
- * Add an agent to the environment. Automatically sets the
2492
- * agent's environment to be this environment.
2493
- * @param {Agent} agent
2494
- * @param {boolean} rebalance - Whether to rebalance if there is a KDTree (defaults to true)
3181
+ * Although `Environment`s inherit {@linkcode Agent} methods
3182
+ * like {@linkcode Agent.set}, {@linkcode Agent.get}, etc. they have
3183
+ * a different `constructor` signature.
3184
+ *
3185
+ * Pass in predefined `Environment` options for:
3186
+ * - `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.)
3187
+ * - `width` &mdash; The width of the `Environment` (used when `torus = true`)
3188
+ * - `height` &mdash; The height of the `Environment` (used when `torus = true`)
3189
+ * @override
3190
+ */
3191
+ function Environment(opts) {
3192
+ if (opts === void 0) { opts = defaultEnvironmentOptions; }
3193
+ var _this = _super.call(this) || this;
3194
+ /** @hidden */
3195
+ _this.agents = [];
3196
+ /** @hidden */
3197
+ _this.agentsById = new Map();
3198
+ /** @hidden */
3199
+ _this.environment = null;
3200
+ /** @hidden */
3201
+ _this.cache = new Map();
3202
+ /** @hidden */
3203
+ _this.helpers = {
3204
+ kdtree: null,
3205
+ network: null,
3206
+ terrain: null
3207
+ };
3208
+ /**
3209
+ * An array of the renderers associated with this `Environment`.
3210
+ * An `Environment` can have multiple renderers, usually one to render
3211
+ * the {@linkcode Agent}s spatially and others for data visualization,
3212
+ * such as a {@linkcode LineChartRenderer}, {@linkcode Histogram}, etc.
3213
+ */
3214
+ _this.renderers = [];
3215
+ /**
3216
+ * This property will always equal the number of tick cycles that
3217
+ * have passed since the `Environment` was created. If you call
3218
+ * {@linkcode tick} so that it goes forward multiple time steps, it will
3219
+ * increase the `time` by that value (not by just `1`, even though
3220
+ * you only called `tick` once).
3221
+ *
3222
+ * ```js
3223
+ * const environment = new Environment();
3224
+ * environment.time; // returns 0
3225
+ *
3226
+ * environment.tick();
3227
+ * environment.time; // returns 1
3228
+ *
3229
+ * environment.tick(3);
3230
+ * environment.time; // returns 4
3231
+ * ```
3232
+ *
3233
+ * @since 0.1.4
3234
+ * */
3235
+ _this.time = 0;
3236
+ _this.opts = Object.assign({}, defaultEnvironmentOptions);
3237
+ _this.opts = Object.assign(_this.opts, opts);
3238
+ _this.width = _this.opts.width;
3239
+ _this.height = _this.opts.height;
3240
+ return _this;
3241
+ }
3242
+ /**
3243
+ * Add an {@linkcode Agent} to this `Environment`. Once this is called,
3244
+ * the `Agent`'s {@link Agent.environment | `environment`} property
3245
+ * will automatically be set to this `Environment`.
3246
+ * @param rebalance - Whether to rebalance if there is a `KDTree` (defaults to true)
2495
3247
  * @since 0.0.5
2496
3248
  */
2497
3249
  Environment.prototype.addAgent = function (agent, rebalance) {
@@ -2553,7 +3305,7 @@ var Environment = /** @class */ (function (_super) {
2553
3305
  return this.agentsById.get(id) || null;
2554
3306
  };
2555
3307
  /**
2556
- * Removes all agents from the environment.
3308
+ * Remove all agents from the environment.
2557
3309
  * @since 0.1.3
2558
3310
  */
2559
3311
  Environment.prototype.clear = function () {
@@ -2563,64 +3315,132 @@ var Environment = /** @class */ (function (_super) {
2563
3315
  }
2564
3316
  };
2565
3317
  /**
2566
- * From the parameter passed to .tick, get a structured TickOptions object.
2567
- * @param {number | TickOptions} opts
3318
+ * From the parameter passed to {@linkcode Environment.tick}, get a structured TickOptions object.
3319
+ * @hidden
2568
3320
  */
2569
3321
  Environment.prototype._getTickOptions = function (opts) {
2570
- var count = defaultTickOptions.count, randomizeOrder = defaultTickOptions.randomizeOrder;
3322
+ var baseOpts = Object.assign({}, defaultTickOptions);
2571
3323
  if (typeof opts === "number") {
2572
- count = opts;
3324
+ baseOpts.count = opts;
2573
3325
  }
2574
3326
  else if (!!opts) {
2575
- count = opts.count || 1;
2576
- }
2577
- if (opts &&
2578
- typeof opts !== "number" &&
2579
- opts.hasOwnProperty("randomizeOrder")) {
2580
- randomizeOrder = opts.randomizeOrder;
3327
+ Object.assign(baseOpts, opts);
2581
3328
  }
2582
- else if (opts === undefined ||
3329
+ if (opts === undefined ||
2583
3330
  (typeof opts !== "number" && !opts.hasOwnProperty("randomizeOrder"))) {
2584
3331
  warnOnce("You called `environment.tick` without specifying a `randomizeOrder` option. Currently this defaults to `false` (i.e. each agent ticks in the order it was added to the environment). However, in **Flocc 0.6.0 this will default to `true`** — agent activation order will default to being randomized.");
2585
3332
  }
2586
- return { count: count, randomizeOrder: randomizeOrder };
3333
+ return baseOpts;
2587
3334
  };
2588
3335
  /**
2589
- * Execute all agent rules.
2590
- * @param { boolean } randomizeOrder
3336
+ * For all agents passed, execute agent rules
3337
+ * @hidden
2591
3338
  */
2592
- Environment.prototype._executeAgentRules = function (randomizeOrder) {
2593
- (randomizeOrder ? shuffle(this.agents) : this.agents).forEach(function (agent) {
2594
- return agent.executeRules();
2595
- });
3339
+ Environment.prototype._executeAgentRules = function (agents) {
3340
+ agents.forEach(function (agent) { return agent === null || agent === void 0 ? void 0 : agent.executeRules(); });
2596
3341
  };
2597
3342
  /**
2598
- * Execute all enqueued agent rules.
2599
- * @param { boolean } randomizeOrder
3343
+ * For all agents passed, execute enqueued agent rules
3344
+ * @hidden
2600
3345
  */
2601
- Environment.prototype._executeEnqueuedAgentRules = function (randomizeOrder) {
2602
- (randomizeOrder ? shuffle(this.agents) : this.agents).forEach(function (agent) {
2603
- return agent.executeEnqueuedRules();
2604
- });
3346
+ Environment.prototype._executeEnqueuedAgentRules = function (agents) {
3347
+ agents.forEach(function (agent) { return agent === null || agent === void 0 ? void 0 : agent.executeEnqueuedRules(); });
2605
3348
  };
2606
3349
  /**
2607
- * Moves the environment forward in time,
2608
- * executing all agent's rules sequentially, followed by
2609
- * any enqueued rules (which are removed with every tick).
2610
- * Can take either a number or a configuration object as a parameter.
2611
- * If a number, the environment will tick forward that many times.
2612
- * @param {number | TickOptions} opts
3350
+ * Runs the `Environment`s tick cycle. Depending on the parameters, one,
3351
+ * some, or all of the {@linkcode Agent}s in the `Environment`
3352
+ * might be activated, and all renderers associated with the
3353
+ * `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.
3354
+ *
3355
+ * ```js
3356
+ * environment.tick(); // ticks once
3357
+ *
3358
+ * // To run multiple tick cycles, you can pass a number
3359
+ * environment.tick(5); // ticks 5 times
3360
+ * ```
3361
+ *
3362
+ * Passing a configuration object (instead of a number) allows
3363
+ * you to have finer control over the tick cycle. The object can
3364
+ * have the following keys:
3365
+ * - `activation`: Either `"uniform"` or `"random"` (defaults to `"uniform"`).
3366
+ * - `activation = "uniform"` &mdash; All `Agent`s in the `Environment` are activated with every tick cycle.
3367
+ * - `activation = "random"` &mdash; One or more `Agent`s are randomly selected to be activated every tick cycle (see `activationCount` below).
3368
+ * - `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.
3369
+ * - `count`: The number of tick cycles to run.
3370
+ * - `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.**
3371
+ *
3372
+ * ```js
3373
+ * // Ticks three times, activating 10 random agents with each tick cycle.
3374
+ * environment.tick({
3375
+ * activation: "random",
3376
+ * activationCount: 10,
3377
+ * count: 3
3378
+ * });
3379
+ * ```
3380
+ *
2613
3381
  * @since 0.0.5
2614
3382
  */
2615
3383
  Environment.prototype.tick = function (opts) {
2616
- var _a = this._getTickOptions(opts), count = _a.count, randomizeOrder = _a.randomizeOrder;
2617
- this._executeAgentRules(randomizeOrder);
2618
- this._executeEnqueuedAgentRules(randomizeOrder);
3384
+ var _a = this._getTickOptions(opts), activation = _a.activation, activationCount = _a.activationCount, count = _a.count, randomizeOrder = _a.randomizeOrder;
3385
+ // for uniform activation, every agent is always activated
3386
+ if (activation === "uniform") {
3387
+ var agentsInOrder = randomizeOrder ? shuffle(this.agents) : this.agents;
3388
+ this._executeAgentRules(agentsInOrder);
3389
+ this._executeEnqueuedAgentRules(agentsInOrder);
3390
+ }
3391
+ // for random activation, the number of agents activated
3392
+ // per tick is determined by the `activationCount` option
3393
+ else if (activation === "random") {
3394
+ if (activationCount === 1) {
3395
+ var agent = sample$1(this.agents);
3396
+ if (agent !== null) {
3397
+ agent.executeRules();
3398
+ agent.executeEnqueuedRules();
3399
+ }
3400
+ }
3401
+ else if (activationCount > 1) {
3402
+ var sampleCount = sampler(activationCount);
3403
+ // this safety check should always return `true`
3404
+ if (isMultipleSampleFunc(sampleCount)) {
3405
+ var agents = sampleCount(this.getAgents());
3406
+ this._executeAgentRules(agents);
3407
+ this._executeEnqueuedAgentRules(agents);
3408
+ }
3409
+ }
3410
+ else {
3411
+ warnOnce("You passed a zero or negative `activationCount` to the Environment's tick options. No agents will be activated.");
3412
+ }
3413
+ }
2619
3414
  if (this.helpers.kdtree)
2620
3415
  this.helpers.kdtree.rebalance();
2621
3416
  var terrain = this.helpers.terrain;
2622
- if (terrain && terrain.rule)
2623
- terrain._loop({ randomizeOrder: randomizeOrder });
3417
+ if (terrain && terrain.rule) {
3418
+ if (activation === "uniform") {
3419
+ terrain._loop({ randomizeOrder: randomizeOrder });
3420
+ }
3421
+ else if (activation === "random") {
3422
+ if (activationCount === 1) {
3423
+ var x = random(0, terrain.width);
3424
+ var y = random(0, terrain.height);
3425
+ terrain._execute(x, y);
3426
+ }
3427
+ else if (activationCount > 1) {
3428
+ var generator = series(terrain.width * terrain.height);
3429
+ var indices = [];
3430
+ while (indices.length < activationCount) {
3431
+ var index = generator.next().value;
3432
+ var x = index % terrain.width;
3433
+ var y = (index / terrain.width) | 0;
3434
+ terrain._execute(x, y);
3435
+ indices.push(index);
3436
+ }
3437
+ }
3438
+ // in synchronous mode, write the buffer to the data
3439
+ if (!terrain.opts.async) {
3440
+ terrain.data = new Uint8ClampedArray(terrain.nextData);
3441
+ }
3442
+ }
3443
+ }
2624
3444
  this.time++;
2625
3445
  if (count > 1) {
2626
3446
  this.tick(count - 1);
@@ -2629,26 +3449,41 @@ var Environment = /** @class */ (function (_super) {
2629
3449
  this.renderers.forEach(function (r) { return r.render(); });
2630
3450
  };
2631
3451
  /**
2632
- * Use a helper with this environment.
2633
- * @param {EnvironmentHelper} e
3452
+ * Use a helper with this environment. A helper can be one of:
3453
+ * - {@linkcode KDTree}
3454
+ * - {@linkcode Network}
3455
+ * - {@linkcode Terrain}
2634
3456
  * @since 0.1.3
2635
3457
  */
2636
- Environment.prototype.use = function (e) {
2637
- if (e instanceof KDTree)
2638
- this.helpers.kdtree = e;
2639
- if (e instanceof Network)
2640
- this.helpers.network = e;
2641
- if (e instanceof Terrain)
2642
- this.helpers.terrain = e;
3458
+ Environment.prototype.use = function (helper) {
3459
+ if (helper instanceof KDTree)
3460
+ this.helpers.kdtree = helper;
3461
+ if (helper instanceof Network)
3462
+ this.helpers.network = helper;
3463
+ if (helper instanceof Terrain)
3464
+ this.helpers.terrain = helper;
2643
3465
  };
2644
3466
  /**
2645
3467
  * Get an array of data associated with agents in the environment by key.
2646
- * Equivalent to calling `environment.getAgents().map(agent => agent.get(key));`
2647
- * Defaults to calculating and storing the result within the same environment tick.
2648
- * If the 2nd parameter is set to `false`, will recalculate and return the result every time.
2649
- * @param {string} key - The key for which to retrieve data.
2650
- * @param {boolean} useCache - Whether or not to cache the result (defaults to true).
2651
- * @return {any[]} Array of data associated with `agent.get(key)` across all agents.
3468
+ * Calling `environment.stat('name')` is equivalent to calling
3469
+ * `environment.getAgents().map(agent => agent.get('name'));`
3470
+ *
3471
+ * By default, calling this will calculate the result at most once
3472
+ * per time cycle, and return the cached value on subsequent calls (until
3473
+ * the next time cycle, when it will recalculate).
3474
+ *
3475
+ * @param key - The key for which to retrieve data.
3476
+ * @param useCache - Whether or not to cache the result.
3477
+ * @returns Array of data associated with `agent.get(key)` across all agents.
3478
+ *
3479
+ * ```js
3480
+ * environment.addAgent(new Agent({ name: "Alice" }));
3481
+ * environment.addAgent(new Agent({ name: "Bob" }));
3482
+ * environment.addAgent(new Agent({ name: "Chaz" }));
3483
+ *
3484
+ * environment.stat('name'); // returns ['Alice', 'Bob', 'Chaz']
3485
+ * ```
3486
+ *
2652
3487
  * @since 0.3.14
2653
3488
  */
2654
3489
  Environment.prototype.stat = function (key, useCache) {
@@ -2669,9 +3504,17 @@ var Environment = /** @class */ (function (_super) {
2669
3504
  };
2670
3505
  /**
2671
3506
  * Pass a function to cache and use the return value within the same environment tick.
2672
- * @param {Function} fn - The function to memoize.
2673
- * @return {any} The return value of the function that was passed.
3507
+ * @param fn - The function to memoize.
3508
+ * @return The return value of the function that was passed.
2674
3509
  * @since 0.3.14
3510
+ *
3511
+ * ```js
3512
+ * // Within the same time cycle, this function will only be called once.
3513
+ * // The cached value will be used on subsequent calls.
3514
+ * const blueAgents = environment.memo(() => {
3515
+ * return environment.getAgents().filter(a => a.get('color') === 'blue');
3516
+ * });
3517
+ * ```
2675
3518
  */
2676
3519
  Environment.prototype.memo = function (fn, key) {
2677
3520
  var serialized = (key ? key + "-" : "") + fn.toString();
@@ -2712,10 +3555,21 @@ var unhash = function (str) {
2712
3555
  };
2713
3556
  var warnOnce$1 = once(console.warn.bind(console));
2714
3557
  /**
2715
- * @since 0.0.5
3558
+ * A `GridEnvironment` is the **deprecated** version of a cellular automata.
3559
+ * It's now recommended that you use a standard {@linkcode Environment} with a
3560
+ * {@linkcode Terrain}. This class will be removed entirely in v0.6.0.
3561
+ *
3562
+ * In a `GridEnvironment` with an {@linkcode ASCIIRenderer}, {@linkcode Agent}s are rendered
3563
+ * using their `"value"` data (a single character).
3564
+ *
3565
+ * @deprecated since 0.4.0
3566
+ * @since 0.0.10
2716
3567
  */
2717
3568
  var GridEnvironment = /** @class */ (function (_super) {
2718
3569
  __extends(GridEnvironment, _super);
3570
+ /**
3571
+ * Create a `GridEnvironment` with the given `width` and `height`.
3572
+ */
2719
3573
  function GridEnvironment(width, height) {
2720
3574
  if (width === void 0) { width = 2; }
2721
3575
  if (height === void 0) { height = 2; }
@@ -2750,6 +3604,7 @@ var GridEnvironment = /** @class */ (function (_super) {
2750
3604
  }
2751
3605
  };
2752
3606
  /**
3607
+ * @hidden
2753
3608
  * @since 0.1.0
2754
3609
  */
2755
3610
  GridEnvironment.prototype.normalize = function (x, y) {
@@ -2764,7 +3619,7 @@ var GridEnvironment = /** @class */ (function (_super) {
2764
3619
  return { x: x, y: y };
2765
3620
  };
2766
3621
  /**
2767
- * For GridEnvironments, `addAgent` takes `x` and `y` values
3622
+ * For `GridEnvironment`s, `addAgent` takes `x` and `y` values
2768
3623
  * and automatically adds a Agent to that cell coordinate.
2769
3624
  * @param {number} x_
2770
3625
  * @param {number} y_
@@ -2793,8 +3648,8 @@ var GridEnvironment = /** @class */ (function (_super) {
2793
3648
  return agent;
2794
3649
  };
2795
3650
  /**
2796
- * For GridEnvironments, `removeAgent` takes `x` and `y` values
2797
- * and removes the Agent (if there is one) at that cell coordinate.
3651
+ * For GridEnvironments, `removeAgentAt` takes `x` and `y` values
3652
+ * and removes the `Agent` (if there is one) at that cell coordinate.
2798
3653
  * @param {number} x_
2799
3654
  * @param {number} y_
2800
3655
  * @since 0.1.0
@@ -2957,6 +3812,7 @@ var GridEnvironment = /** @class */ (function (_super) {
2957
3812
  };
2958
3813
  /**
2959
3814
  * Execute all cell rules.
3815
+ * @hidden
2960
3816
  * @param { boolean } randomizeOrder
2961
3817
  */
2962
3818
  GridEnvironment.prototype._executeCellRules = function (randomizeOrder) {
@@ -2983,6 +3839,7 @@ var GridEnvironment = /** @class */ (function (_super) {
2983
3839
  };
2984
3840
  /**
2985
3841
  * Execute all enqueued cell rules.
3842
+ * @hidden
2986
3843
  * @param { boolean } randomizeOrder
2987
3844
  */
2988
3845
  GridEnvironment.prototype._executeEnqueuedCellRules = function (randomizeOrder) {
@@ -3008,8 +3865,8 @@ var GridEnvironment = /** @class */ (function (_super) {
3008
3865
  }
3009
3866
  };
3010
3867
  /**
3011
- * Override/extend Environment.tick to include the
3012
- * GridEnvironment's cells.
3868
+ * Override/extend {@linkcode Environment.tick} to include the
3869
+ * `GridEnvironment`'s cells.
3013
3870
  * @override
3014
3871
  * @param {number} opts
3015
3872
  */
@@ -3018,11 +3875,11 @@ var GridEnvironment = /** @class */ (function (_super) {
3018
3875
  // execute all cell rules
3019
3876
  this._executeCellRules(randomizeOrder);
3020
3877
  // execute all agent rules
3021
- this._executeAgentRules(randomizeOrder);
3878
+ this._executeAgentRules(randomizeOrder ? shuffle(this.agents) : this.agents);
3022
3879
  // execute all enqueued cell rules
3023
3880
  this._executeEnqueuedCellRules(randomizeOrder);
3024
3881
  // execute all enqueued agent rules
3025
- this._executeEnqueuedAgentRules(randomizeOrder);
3882
+ this._executeEnqueuedAgentRules(randomizeOrder ? shuffle(this.agents) : this.agents);
3026
3883
  this.time++;
3027
3884
  if (count > 1) {
3028
3885
  this.tick(count - 1);
@@ -3035,13 +3892,24 @@ var GridEnvironment = /** @class */ (function (_super) {
3035
3892
 
3036
3893
  var AbstractRenderer = /** @class */ (function () {
3037
3894
  function AbstractRenderer() {
3895
+ /** @hidden */
3038
3896
  this.canvas = document.createElement("canvas");
3897
+ /** @hidden */
3039
3898
  this.context = this.canvas.getContext("2d");
3040
3899
  }
3041
3900
  AbstractRenderer.prototype.render = function () { };
3042
3901
  /**
3043
3902
  * Mount this renderer to a DOM element. Pass either a string representing a
3044
- * CSS selector matching the element (i.e. `"#element-id") or the element itself.
3903
+ * CSS selector matching the element or the element itself.
3904
+ *
3905
+ * ```js
3906
+ * // mounts the renderer to the element with the ID `container`
3907
+ * renderer.mount('#container');
3908
+ *
3909
+ * // mounts the renderer to the element itself
3910
+ * const container = document.getElementById('container');
3911
+ * renderer.mount(container);
3912
+ * ```
3045
3913
  * @param {string | HTMLElement} el
3046
3914
  */
3047
3915
  AbstractRenderer.prototype.mount = function (el) {
@@ -3056,11 +3924,25 @@ var AbstractRenderer = /** @class */ (function () {
3056
3924
 
3057
3925
  var warnOnce$2 = once(console.warn.bind(console));
3058
3926
  /**
3927
+ * An `ASCIIRenderer` renders the {@link Agent | `Agent`}s in
3928
+ * a {@linkcode GridEnvironment}. `Agent`s are rendered
3929
+ * using their `"value"` data (a single character).
3930
+ * Since v0.4.0, this class has been **deprecated**, and it will be removed
3931
+ * entirely in v0.6.0.
3932
+ * ```js
3933
+ * const renderer = new ASCIIRenderer(grid);
3934
+ * renderer.mount("#container-id");
3935
+ * ```
3936
+ * @deprecated since 0.4.0
3059
3937
  * @since 0.0.10
3060
3938
  */
3061
3939
  var ASCIIRenderer = /** @class */ (function (_super) {
3062
3940
  __extends(ASCIIRenderer, _super);
3063
- function ASCIIRenderer(environment, opts) {
3941
+ /**
3942
+ * Create a new `ASCIIRenderer` by passing in the
3943
+ * {@linkcode GridEnvironment} you want to be rendered.
3944
+ */
3945
+ function ASCIIRenderer(environment) {
3064
3946
  var _this = _super.call(this) || this;
3065
3947
  warnOnce$2("As of Flocc v0.5.0, ASCIIEnvironment is **DEPRECATED**. It will be **REMOVED** in v0.6.0. The Terrain helper should be used for 2-dimensional grid-like data, with CanvasRenderer to visualize. Read more about Terrains here: https://flocc.network/docs/terrain");
3066
3948
  _this.environment = environment;
@@ -3069,6 +3951,7 @@ var ASCIIRenderer = /** @class */ (function (_super) {
3069
3951
  return _this;
3070
3952
  }
3071
3953
  /**
3954
+ * Renders the contents of the `ASCIIRenderer`'s {@linkcode GridEnvironment}.
3072
3955
  * @since 0.0.10
3073
3956
  */
3074
3957
  ASCIIRenderer.prototype.render = function () {
@@ -3104,12 +3987,46 @@ var defaultOptions = {
3104
3987
  trace: false
3105
3988
  };
3106
3989
  /**
3990
+ * A `CanvasRenderer` renders an {@linkcode Environment} spatially in two dimensions.
3991
+ * Importantly, it expects that all {@linkcode Agent}s in the `Environment`
3992
+ * have numeric `"x"` and `"y"` values associated with them.
3993
+ *
3994
+ * `CanvasRenderer`s will render all `Agent`s that are visible in the rendered `Environment` space,
3995
+ * with the color of their `"color"` value (defaulting to black).
3996
+ * Depending on the `"shape"` of the `Agent`, additional data might be needed. `Agent` `"shape"`s can be:
3997
+ * - `"circle"` (default) &mdash; Draws a circle centered at the `Agent`'s `"x"` / `"y"` values.
3998
+ * - If the `Agent` has a `"size"` value, uses that for the circle radius (defaults to 1px).
3999
+ * - `"arrow"` &mdash; Draws an arrow centered at the `Agent`'s `"x"` / `"y"` values.
4000
+ * - The arrow will point in the direction of the `Agent`s `"vx"` / `"vy"` values. For example, an `Agent` with `"vx" = 1` and `"vy" = 0` will be rendered as an arrow pointing to the right.
4001
+ * - Also uses the `"size" value.
4002
+ * - `"rect"` &mdash; Draws a rectangle with the upper-left corner at `"x"` / `"y"`.
4003
+ * - Uses the `Agent`'s `"width"` and `"height"` values for the dimensions of the rectangle.
4004
+ * - `"triangle"` &mdash; Draws a triangle centered at the `Agent`'s `"x"` / `"y"` values.
4005
+ * - Also uses the `"size"` value.
4006
+ *
3107
4007
  * @since 0.0.11
3108
4008
  */
3109
4009
  var CanvasRenderer = /** @class */ (function (_super) {
3110
4010
  __extends(CanvasRenderer, _super);
4011
+ /**
4012
+ * The first parameter must be the {@linkcode Environment} that this
4013
+ * `CanvasRenderer` will render.
4014
+ *
4015
+ * The second parameter specifies options, which can include:
4016
+ * - `autoPosition` (*boolean* = `false`) &mdash; For `Environment`s using a {@linkcode Network}, whether to automatically position the `Agent`s.
4017
+ * - `background` (*string* = `"transparent"`) &mdash; The background color to draw before rendering any `Agent`s.
4018
+ * - `connectionColor` (*string* = `"black"`) &mdash; For `Environment`s using a `Network`, the color of lines
4019
+ * - `connectionOpacity` (*number* = `1`) &mdash; For `Environment`s using a `Network`, the opacity of lines
4020
+ * - `connectionWidth` (*number* = `1`) &mdash; For `Environment`s using a `Network`, the width of lines
4021
+ * - `height` (*number* = `500`) &mdash; The height, in pixels, of the canvas on which to render
4022
+ * - `origin` (*{ x: number; y: number }* = `{ x: 0, y: 0 }`) &mdash; The coordinate of the upper-left point of the space to be rendered
4023
+ * - `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)
4024
+ * - `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
4025
+ * - `width` (*number* = `500`) &mdash; The width, in pixels, of the canvas on which to render
4026
+ */
3111
4027
  function CanvasRenderer(environment, opts) {
3112
4028
  var _this = _super.call(this) || this;
4029
+ /** @hidden */
3113
4030
  _this.terrainBuffer = document.createElement("canvas");
3114
4031
  _this.environment = environment;
3115
4032
  environment.renderers.push(_this);
@@ -3130,14 +4047,17 @@ var CanvasRenderer = /** @class */ (function (_super) {
3130
4047
  _this.context.fillRect(0, 0, width, height);
3131
4048
  return _this;
3132
4049
  }
4050
+ /** @hidden */
3133
4051
  CanvasRenderer.prototype.x = function (v) {
3134
4052
  var _a = this.opts, origin = _a.origin, scale = _a.scale;
3135
4053
  return window.devicePixelRatio * scale * (v - origin.x);
3136
4054
  };
4055
+ /** @hidden */
3137
4056
  CanvasRenderer.prototype.y = function (v) {
3138
4057
  var _a = this.opts, origin = _a.origin, scale = _a.scale;
3139
4058
  return window.devicePixelRatio * scale * (v - origin.y);
3140
4059
  };
4060
+ /** @hidden */
3141
4061
  CanvasRenderer.prototype.createCanvas = function () {
3142
4062
  var dpr = window.devicePixelRatio;
3143
4063
  var _a = this.opts, width = _a.width, height = _a.height;
@@ -3146,6 +4066,117 @@ var CanvasRenderer = /** @class */ (function (_super) {
3146
4066
  canvas.height = height * dpr;
3147
4067
  return canvas;
3148
4068
  };
4069
+ /** @hidden */
4070
+ CanvasRenderer.prototype.drawPath = function (points, dx, dy) {
4071
+ if (dx === void 0) { dx = 0; }
4072
+ if (dy === void 0) { dy = 0; }
4073
+ var bufferContext = this.buffer.getContext("2d");
4074
+ points.forEach(function (_a, i) {
4075
+ var px = _a[0], py = _a[1];
4076
+ if (i === 0) {
4077
+ bufferContext.moveTo(px + dx, py + dy);
4078
+ }
4079
+ else {
4080
+ bufferContext.lineTo(px + dx, py + dy);
4081
+ }
4082
+ });
4083
+ };
4084
+ /** @hidden */
4085
+ CanvasRenderer.prototype.drawPathWrap = function (points) {
4086
+ var _this = this;
4087
+ var _a = this, width = _a.width, height = _a.height;
4088
+ var right = false;
4089
+ var left = false;
4090
+ var lower = false;
4091
+ var upper = false;
4092
+ points.forEach(function (_a) {
4093
+ var px = _a[0], py = _a[1];
4094
+ if (_this.x(px) >= width)
4095
+ right = true;
4096
+ if (_this.x(px) < 0)
4097
+ left = true;
4098
+ if (_this.y(py) >= height)
4099
+ lower = true;
4100
+ if (_this.y(py) < 0)
4101
+ upper = true;
4102
+ });
4103
+ if (right)
4104
+ this.drawPath(points, -width, 0);
4105
+ if (left)
4106
+ this.drawPath(points, width, 0);
4107
+ if (lower && right)
4108
+ this.drawPath(points, -width, -height);
4109
+ if (upper && right)
4110
+ this.drawPath(points, -width, height);
4111
+ if (lower && left)
4112
+ this.drawPath(points, width, -height);
4113
+ if (upper && left)
4114
+ this.drawPath(points, width, height);
4115
+ if (lower)
4116
+ this.drawPath(points, 0, -height);
4117
+ if (upper)
4118
+ this.drawPath(points, 0, height);
4119
+ };
4120
+ /** @hidden */
4121
+ CanvasRenderer.prototype.drawCircle = function (x, y, r) {
4122
+ var bufferContext = this.buffer.getContext("2d");
4123
+ bufferContext.moveTo(this.x(x), this.y(y));
4124
+ bufferContext.arc(this.x(x), this.y(y), r, 0, 2 * Math.PI);
4125
+ };
4126
+ /** @hidden */
4127
+ CanvasRenderer.prototype.drawCircleWrap = function (x, y, size) {
4128
+ var _a = this, width = _a.width, height = _a.height;
4129
+ if (this.x(x + size) >= width) {
4130
+ this.drawCircle(x - width, y, size);
4131
+ if (this.y(y + size) >= height)
4132
+ this.drawCircle(x - width, y - height, size);
4133
+ if (this.y(y - size) < 0)
4134
+ this.drawCircle(x - width, y + height, size);
4135
+ }
4136
+ if (this.x(x - size) < 0) {
4137
+ this.drawCircle(x + width, y, size);
4138
+ if (this.y(y + size) >= height)
4139
+ this.drawCircle(x + width, y - height, size);
4140
+ if (this.y(y - size) < 0)
4141
+ this.drawCircle(x + width, y + height, size);
4142
+ }
4143
+ if (this.y(y + size) > height)
4144
+ this.drawCircle(x, y - height, size);
4145
+ if (this.y(y - size) < 0)
4146
+ this.drawCircle(x, y + height, size);
4147
+ };
4148
+ /**
4149
+ * Draw a rectangle centered at (x, y). Automatically calculates the offset
4150
+ * for both width and height.
4151
+ * @hidden
4152
+ */
4153
+ CanvasRenderer.prototype.drawRect = function (x, y, width, height) {
4154
+ var bufferContext = this.buffer.getContext("2d");
4155
+ var dpr = window.devicePixelRatio;
4156
+ bufferContext.fillRect(this.x(x) - (width * dpr) / 2, this.y(y) - (height * dpr) / 2, width * dpr, height * dpr);
4157
+ };
4158
+ /** @hidden */
4159
+ CanvasRenderer.prototype.drawRectWrap = function (x, y, w, h) {
4160
+ var _a = this.opts, width = _a.width, height = _a.height;
4161
+ if (this.x(x + w / 2) >= width) {
4162
+ this.drawRect(x - width, y, w, h);
4163
+ if (this.y(y + h / 2) >= height)
4164
+ this.drawRect(x - width, y - height, w, h);
4165
+ if (this.y(y - height / 2) < 0)
4166
+ this.drawRect(x - width, y + height, w, h);
4167
+ }
4168
+ if (this.x(x - w / 2) < 0) {
4169
+ this.drawRect(x + width, y, w, h);
4170
+ if (this.y(y + h / 2) >= height)
4171
+ this.drawRect(x + width, y - height, w, h);
4172
+ if (this.y(y - height / 2) < 0)
4173
+ this.drawRect(x + width, y + height, w, h);
4174
+ }
4175
+ if (this.y(y + h / 2) > height)
4176
+ this.drawRect(x, y - height, w, h);
4177
+ if (this.y(y - height / 2) < 0)
4178
+ this.drawRect(x, y + height, w, h);
4179
+ };
3149
4180
  CanvasRenderer.prototype.render = function () {
3150
4181
  var _this = this;
3151
4182
  var _a = this, buffer = _a.buffer, context = _a.context, environment = _a.environment, width = _a.width, height = _a.height, opts = _a.opts, terrainBuffer = _a.terrainBuffer;
@@ -3233,28 +4264,36 @@ var CanvasRenderer = /** @class */ (function (_super) {
3233
4264
  var _vx = 3 * size * (vx / norm) * dpr;
3234
4265
  var _vy = 3 * size * (vy / norm) * dpr;
3235
4266
  bufferContext.beginPath();
3236
- bufferContext.save();
3237
- bufferContext.translate(_this.x(x), _this.y(y));
3238
- bufferContext.moveTo(1.5 * _vx, 1.5 * _vy);
3239
- bufferContext.lineTo(_vy / 2, -_vx / 2);
3240
- bufferContext.lineTo(-_vy / 2, _vx / 2);
3241
- bufferContext.restore();
4267
+ var points = [
4268
+ [_this.x(x) + 1.5 * _vx, _this.y(y) + 1.5 * _vy],
4269
+ [_this.x(x) + _vy / 2, _this.y(y) - _vx / 2],
4270
+ [_this.x(x) - _vy / 2, _this.y(y) + _vx / 2]
4271
+ ];
4272
+ _this.drawPath(points);
4273
+ if (environment.opts.torus)
4274
+ _this.drawPathWrap(points);
3242
4275
  }
3243
4276
  else if (shape === "rect") {
3244
4277
  var _h = agent.getData(), _j = _h.width, width_1 = _j === void 0 ? 1 : _j, _k = _h.height, height_1 = _k === void 0 ? 1 : _k;
3245
- bufferContext.fillRect(_this.x(x) - (width_1 * dpr) / 2, _this.y(y) - (height_1 * dpr) / 2, width_1 * dpr, height_1 * dpr);
4278
+ _this.drawRect(x, y, width_1, height_1);
4279
+ if (environment.opts.torus)
4280
+ _this.drawRectWrap(x, y, width_1, height_1);
3246
4281
  }
3247
4282
  else if (shape === "triangle") {
3248
4283
  bufferContext.beginPath();
3249
- bufferContext.save();
3250
- bufferContext.translate(_this.x(x), _this.y(y));
3251
- bufferContext.moveTo(0, -size / 2);
3252
- bufferContext.lineTo(size / 2, size / 2);
3253
- bufferContext.lineTo(-size / 2, size / 2);
3254
- bufferContext.restore();
4284
+ var points = [
4285
+ [_this.x(x), _this.y(y) - size / 2],
4286
+ [_this.x(x) + size / 2, _this.y(y) + size / 2],
4287
+ [_this.x(x) - size / 2, _this.y(y) + size / 2]
4288
+ ];
4289
+ _this.drawPath(points);
4290
+ if (environment.opts.torus)
4291
+ _this.drawPathWrap(points);
3255
4292
  }
3256
4293
  else if (shape === "circle" || shape === undefined) {
3257
- bufferContext.arc(_this.x(x), _this.y(y), size * dpr, 0, 2 * Math.PI);
4294
+ _this.drawCircle(x, y, size * dpr);
4295
+ if (environment.opts.torus)
4296
+ _this.drawCircleWrap(x, y, size);
3258
4297
  }
3259
4298
  bufferContext.fill();
3260
4299
  if (text) {
@@ -3276,22 +4315,6 @@ var CanvasRenderer = /** @class */ (function (_super) {
3276
4315
  return CanvasRenderer;
3277
4316
  }(AbstractRenderer));
3278
4317
 
3279
- /**
3280
- * Maps a number x, from the given domain aMin --> aMax,
3281
- * onto the given range bMin --> bMax.
3282
- * Ex: remap(5, 0, 10, 0, 100) => 50.
3283
- * @param {number} x
3284
- * @param {number} aMin
3285
- * @param {number} aMax
3286
- * @param {number} bMin
3287
- * @param {number} bMax
3288
- * @returns {number} The remapped value.
3289
- * @since 0.0.5
3290
- */
3291
- function remap(x, aMin, aMax, bMin, bMax) {
3292
- return bMin + ((bMax - bMin) * (x - aMin)) / (aMax - aMin);
3293
- }
3294
-
3295
4318
  /// <reference path="../types/NRange.d.ts" />
3296
4319
  function extractRoundNumbers(range) {
3297
4320
  var min = range.min, max = range.max;
@@ -3603,7 +4626,7 @@ var LineChartRenderer = /** @class */ (function (_super) {
3603
4626
  if (opts.autoScroll && t >= width) {
3604
4627
  x -= t - width;
3605
4628
  }
3606
- else if (opts.autoScale && t >= width) {
4629
+ else if (opts.autoScale) {
3607
4630
  x *= width / t;
3608
4631
  }
3609
4632
  return x | 0;
@@ -3651,7 +4674,7 @@ var LineChartRenderer = /** @class */ (function (_super) {
3651
4674
  context.restore();
3652
4675
  // draw time values for horizontal axis
3653
4676
  var min = opts.autoScroll && t >= width ? t - width : 0;
3654
- var max = opts.autoScale && t >= width ? t : width;
4677
+ var max = opts.autoScale ? Math.max(t, 5) : width;
3655
4678
  var timeRange = { min: min, max: max };
3656
4679
  var timeMarkers = extractRoundNumbers(timeRange);
3657
4680
  context.save();
@@ -3731,14 +4754,61 @@ var precision = function (n, d) {
3731
4754
  };
3732
4755
  var escapeStringQuotes = function (s) { return "\"" + s.replace(/"/g, '\\"') + "\""; };
3733
4756
  /**
4757
+ * A `TableRenderer` renders an HTML table (for browsers only) or CSV (comma-separated value)
4758
+ * representation of {@linkcode Agent} data.
4759
+ *
4760
+ * ```js
4761
+ * for (let i = 0; i < 3; i++) {
4762
+ * environment.addAgent(new Agent({
4763
+ * x: i * 10,
4764
+ * y: i - 2
4765
+ * }));
4766
+ * }
4767
+ *
4768
+ * const renderer = new TableRenderer(environment);
4769
+ * renderer.columns = ['x', 'y'];
4770
+ * renderer.mount('#container');
4771
+ * environment.tick();
4772
+ * ```
4773
+ *
4774
+ * The `TableRenderer` renders:
4775
+ *
4776
+ * |x |y |
4777
+ * |----|----|
4778
+ * |0 |-2 |
4779
+ * |10 |-1 |
4780
+ * |20 |0 |
4781
+ *
3734
4782
  * @since 0.5.0
3735
4783
  */
3736
4784
  var TableRenderer = /** @class */ (function (_super) {
3737
4785
  __extends(TableRenderer, _super);
4786
+ /**
4787
+ * The first parameter must be the {@linkcode Environment} that this
4788
+ * `TableRenderer` will render.
4789
+ *
4790
+ * The second parameter specifies options, which can include:
4791
+ * - `"type"` (`"csv"` | `"table"` = `"table"`) &mdash; Whether to render output in CSV or HTML `<table>` format
4792
+ * - `"filter"` &mdash; Include a function (`Agent` => `boolean`) to specify which rows to include in the output. For example, if you only want to include `Agent`s with an x value greater than 100:
4793
+ * ```js
4794
+ * const renderer = new TableRenderer(environment, {
4795
+ * filter: agent => {
4796
+ * return agent.get('x') > 100;
4797
+ * }
4798
+ * });
4799
+ * ```
4800
+ * - `"limit"` (*number* = `Infinity`) &mdash; The maximum number of rows (`Agent`s) to render. If using a `filter` function, applies the `limit` *after* filtering.
4801
+ * - `"sortKey"` (*string* = `null`) &mdash; Sort the `Agent` data by this key of data
4802
+ * - `"order"` (`"asc"` | `"desc"` = `"desc"`) &mdash; When using a `"sortKey"`, specify whether `Agent`s should be listed in *asc*ending or *desc*ending order
4803
+ * - `"precision"` (*number* = `3`) &mdash; For floating point values, the number of decimal places to display
4804
+ * - `"refresh"` (*number* = `500`) &mdash; The number of milliseconds that should elapse between re-rendering (if this happens too quickly the effect can be visually jarring)
4805
+ */
3738
4806
  function TableRenderer(environment, options) {
3739
4807
  if (options === void 0) { options = {}; }
3740
4808
  var _this = _super.call(this) || this;
4809
+ /** @hidden */
3741
4810
  _this.lastRendered = +new Date();
4811
+ /** @hidden */
3742
4812
  _this.opts = Object.assign({}, defaultTableRendererOptions);
3743
4813
  _this.environment = environment;
3744
4814
  environment.renderers.push(_this);
@@ -3748,7 +4818,16 @@ var TableRenderer = /** @class */ (function (_super) {
3748
4818
  }
3749
4819
  /**
3750
4820
  * Mount this renderer to a DOM element. Pass either a string representing a
3751
- * CSS selector matching the element (i.e. `"#element-id") or the element itself.
4821
+ * CSS selector matching the element or the element itself.
4822
+ *
4823
+ * ```js
4824
+ * // mounts the renderer to the element with the ID `container`
4825
+ * renderer.mount('#container');
4826
+ *
4827
+ * // mounts the renderer to the element itself
4828
+ * const container = document.getElementById('container');
4829
+ * renderer.mount(container);
4830
+ * ```
3752
4831
  * @override
3753
4832
  * @param {string | HTMLElement} el
3754
4833
  */
@@ -3761,6 +4840,7 @@ var TableRenderer = /** @class */ (function (_super) {
3761
4840
  }
3762
4841
  this.table = container;
3763
4842
  };
4843
+ /** @hidden */
3764
4844
  TableRenderer.prototype.serializeColumns = function (joiner, start, end, escape) {
3765
4845
  if (start === void 0) { start = ""; }
3766
4846
  if (end === void 0) { end = ""; }
@@ -3772,6 +4852,7 @@ var TableRenderer = /** @class */ (function (_super) {
3772
4852
  return "";
3773
4853
  return start + columns.join(joiner) + end;
3774
4854
  };
4855
+ /** @hidden */
3775
4856
  TableRenderer.prototype.serializeRows = function (cellJoiner, rowJoiner, start, end, rowStart, rowEnd, escape) {
3776
4857
  var _this = this;
3777
4858
  if (start === void 0) { start = ""; }
@@ -3820,6 +4901,7 @@ var TableRenderer = /** @class */ (function (_super) {
3820
4901
  .join(rowJoiner) +
3821
4902
  end);
3822
4903
  };
4904
+ /** @hidden */
3823
4905
  TableRenderer.prototype.renderCSV = function () {
3824
4906
  var columns = this.serializeColumns(",", "", "", true);
3825
4907
  if (columns === "")
@@ -3829,12 +4911,28 @@ var TableRenderer = /** @class */ (function (_super) {
3829
4911
  return columns;
3830
4912
  return columns + "\n" + rows;
3831
4913
  };
4914
+ /** @hidden */
3832
4915
  TableRenderer.prototype.renderHTMLTable = function () {
3833
4916
  var thead = this.serializeColumns("</td><td>", "<thead><tr><td>", "</td></tr></thead>");
3834
4917
  var tbody = this.serializeRows("</td><td>", "", "<tbody>", "</tbody>", "<tr><td>", "</td></tr>");
3835
4918
  return "<table>" + thead + tbody + "</table>";
3836
4919
  };
3837
4920
  /**
4921
+ * Returns the outer HTML of the table or the CSV data as a string. This can be useful for exporting data, particularly in a Node.js environment as opposed to in a browser. For instance, in a Node.js script, you could write the CSV data to a file as follows:
4922
+ *
4923
+ * ```js
4924
+ * const fs = require('fs'); // import the file system module
4925
+ *
4926
+ * const environment = new Environment();
4927
+ * for (let i = 0; i < 3; i++) environment.addAgent(new Agent({ i }));
4928
+ *
4929
+ * const renderer = new TableRenderer(environment, { type: 'csv' });
4930
+ * renderer.columns = ['i'];
4931
+ *
4932
+ * // write the TableRenderer's output to a CSV file named data.csv
4933
+ * fs.writeFileSync('./data.csv', renderer.output());
4934
+ * ```
4935
+ *
3838
4936
  * @since 0.5.0
3839
4937
  */
3840
4938
  TableRenderer.prototype.output = function () {
@@ -3860,22 +4958,6 @@ var TableRenderer = /** @class */ (function (_super) {
3860
4958
  return TableRenderer;
3861
4959
  }(AbstractRenderer));
3862
4960
 
3863
- /**
3864
- * Restricts a number x to the range min --> max.
3865
- * @param {number} x
3866
- * @param {number} min
3867
- * @param {number} max
3868
- * @return {number} The clamped value.
3869
- * @since 0.0.5
3870
- */
3871
- function clamp(x, min, max) {
3872
- if (x < min)
3873
- return min;
3874
- if (x > max)
3875
- return max;
3876
- return x;
3877
- }
3878
-
3879
4961
  var PADDING_AT_BOTTOM$1 = 60;
3880
4962
  var PADDING_AT_LEFT$1 = 60;
3881
4963
  var isAxisObject = function (obj) {
@@ -3892,12 +4974,48 @@ var defaultHeatmapOptions = {
3892
4974
  };
3893
4975
  var warnOnce$3 = once(console.warn.bind(console));
3894
4976
  /**
4977
+ * A `Heatmap` can be used to visualize the distribution of {@linkcode Agent}s across two metrics.
4978
+ * While {@linkcode Histogram}s are useful for showing the distribution of `Agent`s along a single metric
4979
+ * (or on multiple metrics using the same scale), a `Heatmap` can show how two metrics relate to one another &mdash;
4980
+ * correlation, inverse correlation, in a nonlinear manner, randomly (no correlation), etc.
4981
+ *
4982
+ * <img src="https://cms.flocc.network/wp-content/uploads/2020/11/heatmap-basic.png" />
4983
+ *
4984
+ * Note above that, although the output appears similar to what a {@linkcode CanvasRenderer} might output, the `y` axis is reversed here &mdash; low values are at the bottom and high at the top, whereas on a `CanvasRenderer` high values are at the bottom and low at the top.
4985
+ *
3895
4986
  * @since 0.5.8
3896
4987
  */
3897
4988
  var Heatmap = /** @class */ (function (_super) {
3898
4989
  __extends(Heatmap, _super);
4990
+ /**
4991
+ * The first parameter must be the {@linkcode Environment} that this
4992
+ * `Heatmap` will render.
4993
+ *
4994
+ * The second parameter specifies options, which can include:
4995
+ * - `from` (*string* = `"white"`) &mdash; The color (name, hex value, or RGB) to draw when a cell contains `0` {@linkcode Agent}s
4996
+ * - `to` (*string* = `"black"`) &mdash; The color (name, hex value, or RGB) to draw when a cell contains the highest number of `Agent`s
4997
+ * - `x` and `y` can be either:
4998
+ * - *string* = `"x"`/`"y"` respectively &mdash; The name of `Agent` data to measure along the `x`/`y` axis
4999
+ * - *{ buckets: number; key: string; min: number; max: number }* = `{ buckets: 10, key: 'x' | 'y', min: 0, max: 1 }` &mdash; Include the number of buckets to divide the range `min → max` into, along with the name of `Agent` data
5000
+ * - `width` (*number* = `500`) &mdash; The width, in pixels, of the canvas on which to render
5001
+ * - `height` (*number* = `500`) &mdash; The height, in pixels, of the canvas on which to render
5002
+ * - `scale` (either `"relative"` or `"fixed"`, defaults to `"relative"`)
5003
+ * - `"relative"` &mdash; The maximum number of `Agent`s in any single cell is automatically used as the highest value in the scale. This updates over time based on `Agent` distribution.
5004
+ * - `"fixed"` &mdash; You supply the number to use as the maximum value (see `max` below).
5005
+ * - `max` (optional, *number*) &mdash; If you use `scale = "fixed"`, then setting a `max` will cause cells with that number (or higher) of `Agent`s to be drawn using the `to` color.
5006
+ *
5007
+ * ```js
5008
+ * // plots the correlation between age of agents (on the x-axis)
5009
+ * // vs. their wealth (on the y-axis)
5010
+ * const heatmap = new Heatmap(environment, {
5011
+ * x: 'age',
5012
+ * y: 'wealth'
5013
+ * });
5014
+ * ```
5015
+ */
3899
5016
  function Heatmap(environment, opts) {
3900
5017
  var _this = _super.call(this) || this;
5018
+ /** @hidden */
3901
5019
  _this.opts = defaultHeatmapOptions;
3902
5020
  _this.environment = environment;
3903
5021
  _this.opts = Object.assign({}, _this.opts, opts);
@@ -3916,7 +5034,7 @@ var Heatmap = /** @class */ (function (_super) {
3916
5034
  }
3917
5035
  /**
3918
5036
  * Map a value (on the range x-min to x-max) onto canvas space to draw it along the x-axis.
3919
- * @param value
5037
+ * @hidden
3920
5038
  */
3921
5039
  Heatmap.prototype.x = function (value) {
3922
5040
  var width = this.width;
@@ -3924,12 +5042,13 @@ var Heatmap = /** @class */ (function (_super) {
3924
5042
  };
3925
5043
  /**
3926
5044
  * Map a value (on the range y-min to y-max) onto canvas space to draw it along the y-axis.
3927
- * @param value
5045
+ * @hidden
3928
5046
  */
3929
5047
  Heatmap.prototype.y = function (value) {
3930
5048
  var height = this.height;
3931
5049
  return remap(value, this.getMin("y"), this.getMax("y"), height - PADDING_AT_BOTTOM$1, 0);
3932
5050
  };
5051
+ /** @hidden */
3933
5052
  Heatmap.prototype.getKey = function (axis) {
3934
5053
  var a = this.opts[axis];
3935
5054
  if (isAxisObject(a)) {
@@ -3939,12 +5058,14 @@ var Heatmap = /** @class */ (function (_super) {
3939
5058
  return a;
3940
5059
  }
3941
5060
  };
5061
+ /** @hidden */
3942
5062
  Heatmap.prototype.getBuckets = function (axis) {
3943
5063
  var a = this.opts[axis];
3944
5064
  if (isAxisObject(a) && a.hasOwnProperty("buckets"))
3945
5065
  return a.buckets;
3946
5066
  return 10;
3947
5067
  };
5068
+ /** @hidden */
3948
5069
  Heatmap.prototype.getMin = function (axis) {
3949
5070
  var a = this.opts[axis];
3950
5071
  if (isAxisObject(a) && a.hasOwnProperty("min")) {
@@ -3954,6 +5075,7 @@ var Heatmap = /** @class */ (function (_super) {
3954
5075
  return 0;
3955
5076
  }
3956
5077
  };
5078
+ /** @hidden */
3957
5079
  Heatmap.prototype.getMax = function (axis) {
3958
5080
  var a = this.opts[axis];
3959
5081
  if (isAxisObject(a) && a.hasOwnProperty("max")) {
@@ -3963,6 +5085,7 @@ var Heatmap = /** @class */ (function (_super) {
3963
5085
  return 1;
3964
5086
  }
3965
5087
  };
5088
+ /** @hidden */
3966
5089
  Heatmap.prototype.drawMarkers = function () {
3967
5090
  var _a = this, context = _a.context, width = _a.width, height = _a.height;
3968
5091
  var _b = this.opts, from = _b.from, to = _b.to;
@@ -4015,6 +5138,7 @@ var Heatmap = /** @class */ (function (_super) {
4015
5138
  }
4016
5139
  }
4017
5140
  };
5141
+ /** @hidden */
4018
5142
  Heatmap.prototype.updateScale = function () {
4019
5143
  var _a = this, context = _a.context, environment = _a.environment, height = _a.height;
4020
5144
  var scale = this.opts.scale;
@@ -4036,6 +5160,7 @@ var Heatmap = /** @class */ (function (_super) {
4036
5160
  this.lastUpdatedScale = new Date();
4037
5161
  }
4038
5162
  };
5163
+ /** @hidden */
4039
5164
  Heatmap.prototype.drawRectangles = function () {
4040
5165
  var _a = this, canvas = _a.canvas, environment = _a.environment, width = _a.width, height = _a.height;
4041
5166
  var _b = this.opts, scale = _b.scale, from = _b.from, to = _b.to;
@@ -4062,11 +5187,13 @@ var Heatmap = /** @class */ (function (_super) {
4062
5187
  }
4063
5188
  context.globalAlpha = 1;
4064
5189
  };
5190
+ /** @hidden */
4065
5191
  Heatmap.prototype.resetBuckets = function () {
4066
5192
  for (var i = 0; i < this.getBuckets("x") * this.getBuckets("y"); i++) {
4067
5193
  this.buckets[i] = 0;
4068
5194
  }
4069
5195
  };
5196
+ /** @hidden */
4070
5197
  Heatmap.prototype.updateBuckets = function () {
4071
5198
  var _this = this;
4072
5199
  var environment = this.environment;
@@ -4109,134 +5236,8 @@ var Heatmap = /** @class */ (function (_super) {
4109
5236
  }(AbstractRenderer));
4110
5237
 
4111
5238
  /**
4112
- * Given a mean and standard deviation,
4113
- * returns a value from a normal/Gaussian distribution.
4114
- * @param {number} mean
4115
- * @param {number} sd
4116
- * @returns {number}
4117
- * @since 0.0.8
4118
- */
4119
- function gaussian(mean, sd) {
4120
- if (mean === void 0) { mean = 0; }
4121
- if (sd === void 0) { sd = 1; }
4122
- var y, x1, x2, w;
4123
- do {
4124
- x1 = 2 * uniform() - 1;
4125
- x2 = 2 * uniform() - 1;
4126
- w = x1 * x1 + x2 * x2;
4127
- } while (w >= 1);
4128
- w = Math.sqrt((-2 * Math.log(w)) / w);
4129
- y = x1 * w;
4130
- return y * sd + mean;
4131
- }
4132
-
4133
- /// <reference path="../types/Point.d.ts" />
4134
- /**
4135
- * Finds the Manhattan distance between `p1` and `p2`.
4136
- * The inputs may be plain objects
4137
- * with `x`, `y`, and/or `z` keys, or Agent-like objects who have
4138
- * `x`, `y`, and/or `z` data.
4139
- * @param {Point|Agent} p1
4140
- * @param {Point|Agent} p2
4141
- * @return {number} The Manhattan distance between p1 and p2.
4142
- * @since 0.0.12
4143
- */
4144
- function manhattanDistance(p1, p2) {
4145
- var x1 = (p1 instanceof Agent ? p1.get("x") : p1.x) || 0;
4146
- var y1 = (p1 instanceof Agent ? p1.get("y") : p1.y) || 0;
4147
- var z1 = (p1 instanceof Agent ? p1.get("z") : p1.z) || 0;
4148
- var x2 = (p2 instanceof Agent ? p2.get("x") : p2.x) || 0;
4149
- var y2 = (p2 instanceof Agent ? p2.get("y") : p2.y) || 0;
4150
- var z2 = (p2 instanceof Agent ? p2.get("z") : p2.z) || 0;
4151
- var dx = Math.abs(x2 - x1);
4152
- var dy = Math.abs(y2 - y1);
4153
- var dz = Math.abs(z2 - z1);
4154
- // distance for toroidal environments
4155
- if (p1 instanceof Agent &&
4156
- p2 instanceof Agent &&
4157
- p1.environment &&
4158
- p2.environment &&
4159
- p1.environment === p2.environment &&
4160
- p1.environment.width &&
4161
- p1.environment.height &&
4162
- p1.environment.opts.torus) {
4163
- var environment = p1.environment;
4164
- var width = environment.width, height = environment.height;
4165
- if (dx > width / 2)
4166
- dx = width - dx;
4167
- if (dy > height / 2)
4168
- dy = height - dy;
4169
- }
4170
- return dx + dy + dz;
4171
- }
4172
-
4173
- /**
4174
- * Seed a pseudo-random number generator with a value.
4175
- * This can be used to produce predictable pseudo-random numbers.
4176
- * When calling `utils.random`, `utils.sample`, or other functions
4177
- * relying on randomness with the same initial seed, the values
4178
- * generated will always be the same.
4179
- *
4180
- * Predictable randomness can be turned off by calling `seed(null)`, or reset
4181
- * by calling `seed(value)` again with the initial value you used.
4182
- * @param value
4183
- * @since 0.5.0
4184
- */
4185
- var seed = function (value) { return PRNG.seed(value); };
4186
-
4187
- /**
4188
- * Find the standard deviation of an Array of numbers.
4189
- * @param {Array<number>} arr
4190
- * @returns {number}
4191
- * @since 0.0.16
4192
- */
4193
- function stdDev(arr) {
4194
- if (arr.length === 0)
4195
- return null;
4196
- var ave = mean(arr);
4197
- return Math.sqrt(mean(arr.map(function (x) { return (x - ave) * (x - ave); })));
4198
- }
4199
-
4200
- /**
4201
- * @since 0.1.4
5239
+ * The current version of the Flocc library.
4202
5240
  */
4203
- function zfill(str, width) {
4204
- if (width === void 0) { width = 0; }
4205
- var output = str;
4206
- while (output.length < width)
4207
- output = "0" + output;
4208
- return output;
4209
- }
4210
-
4211
-
4212
-
4213
- var utils = /*#__PURE__*/Object.freeze({
4214
- __proto__: null,
4215
- clamp: clamp,
4216
- distance: distance,
4217
- gaussian: gaussian,
4218
- gcd: gcd,
4219
- manhattanDistance: manhattanDistance,
4220
- lerp: lerp,
4221
- remap: remap,
4222
- random: random,
4223
- sample: sample$1,
4224
- sampler: sampler,
4225
- seed: seed,
4226
- series: series,
4227
- shuffle: shuffle,
4228
- sum: sum,
4229
- max: max,
4230
- mean: mean,
4231
- median: median,
4232
- min: min,
4233
- percentile: percentile,
4234
- stdDev: stdDev,
4235
- uniform: uniform,
4236
- uuid: uuid$1,
4237
- zfill: zfill
4238
- });
4239
-
4240
- var version = "0.5.18";
5241
+ var version = "0.5.21";
4241
5242
 
4242
5243
  export { ASCIIRenderer, Agent, CanvasRenderer, Colors, Environment, GridEnvironment, Heatmap, Histogram, KDTree, LineChartRenderer, Network, NumArray, Rule, TableRenderer, Terrain, version as VERSION, Vector, utils };