@woosh/meep-engine 2.50.3 → 2.52.0

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.
Files changed (207) hide show
  1. package/editor/actions/concrete/WriteGridValueAction.js +13 -18
  2. package/editor/ecs/component/editors/Sampler2DEditor.js +2 -2
  3. package/editor/process/SymbolicDisplayProcess.js +1 -1
  4. package/editor/process/symbolic/buildThreeJSHelperEntity.js +1 -1
  5. package/editor/process/symbolic/makeCameraSymbolicDisplay.js +1 -1
  6. package/editor/process/symbolic/makeGridPositionSymbolDisplay.js +1 -1
  7. package/editor/process/symbolic/makeLightSymbolicDisplay.js +1 -1
  8. package/editor/process/symbolic/makePathSymbolicDisplay.js +1 -1
  9. package/editor/process/symbolic/makePositionedIconDisplaySymbol.js +1 -1
  10. package/editor/view/ecs/components/GridObstacleController.js +2 -2
  11. package/editor/view/ecs/components/TerrainController.js +2 -2
  12. package/package.json +1 -1
  13. package/samples/terrain/editor.js +2 -2
  14. package/src/core/NumberFormat.js +0 -71
  15. package/src/core/UUID.spec.js +8 -0
  16. package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.d.ts +4 -0
  17. package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +58 -55
  18. package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.spec.js +54 -0
  19. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +3 -3
  20. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.spec.js +60 -0
  21. package/src/core/bvh2/bvh3/query/BVHQueryAny.js +16 -0
  22. package/src/core/bvh2/bvh3/query/bvh_collect_user_data.js +5 -5
  23. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +2 -3
  24. package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.spec.js +22 -0
  25. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +2 -2
  26. package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.spec.js +64 -0
  27. package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +2 -3
  28. package/src/core/bvh2/visual/convert_bvh_to_dot_format_string.js +2 -2
  29. package/src/core/cache/Cache.js +3 -5
  30. package/src/core/cache/CacheElement.js +1 -0
  31. package/src/core/geom/2d/quad-tree/PointQuadTree.js +10 -0
  32. package/src/core/geom/3d/aabb/aabb3_array_combine.js +3 -3
  33. package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +41 -0
  34. package/src/core/geom/3d/topology/struct/TopoMesh.js +3 -2
  35. package/src/core/geom/3d/topology/struct/prototypeBinaryTopology.js +4 -4
  36. package/src/core/geom/Vector2.d.ts +9 -0
  37. package/src/core/geom/Vector2.js +8 -22
  38. package/src/core/geom/Vector2.spec.js +153 -0
  39. package/src/core/graph/{convertGraphToDotString.js → convert_graph_to_dot_string.js} +1 -1
  40. package/src/core/graph/convert_graph_to_dot_string.spec.js +28 -0
  41. package/src/core/math/noise/sdnoise.js +5 -7
  42. package/src/core/math/noise/sdnoise.spec.js +87 -0
  43. package/src/core/model/ModuleRegistry.js +2 -4
  44. package/src/core/model/ModuleRegistry.spec.js +31 -0
  45. package/src/core/model/reactive/js/compileReactiveToJS.spec.js +14 -0
  46. package/src/core/model/reactive/model/logic/ReactiveAnd.spec.js +31 -1
  47. package/src/core/model/reactive/model/logic/ReactiveOr.spec.js +53 -0
  48. package/src/core/model/stat/LinearModifier.js +2 -2
  49. package/src/core/model/stat/LinearModifier.spec.js +62 -0
  50. package/src/core/model/stat/Stat.js +12 -0
  51. package/src/core/model/stat/Stat.spec.js +36 -0
  52. package/src/core/primitives/array/computeStridedIntegerArrayHash.spec.js +28 -0
  53. package/src/core/primitives/numbers/number_format_by_thousands.js +14 -0
  54. package/src/core/primitives/numbers/number_pretty_print.js +49 -0
  55. package/src/core/primitives/strings/computeStringHash.spec.js +12 -5
  56. package/src/core/process/BaseProcess.js +8 -8
  57. package/src/engine/Clock.js +30 -29
  58. package/src/engine/Clock.spec.js +26 -0
  59. package/src/engine/{Platform.js → browserInfo.js} +1 -5
  60. package/src/engine/ecs/EntityBuilder.js +3 -1
  61. package/src/engine/ecs/EntityBuilder.spec.js +21 -0
  62. package/src/engine/ecs/fow/FogOfWar.js +48 -54
  63. package/src/engine/ecs/gui/GUIElement.js +1 -1
  64. package/src/engine/ecs/gui/position/ViewportPosition.js +3 -3
  65. package/src/engine/ecs/{systems → renderable}/RenderSystem.d.ts +1 -1
  66. package/src/engine/ecs/{systems → renderable}/RenderSystem.js +10 -38
  67. package/src/engine/ecs/renderable/Renderable.d.ts +25 -0
  68. package/src/engine/ecs/{components → renderable}/Renderable.js +18 -83
  69. package/src/engine/ecs/renderable/Renderable.spec.js +10 -0
  70. package/src/engine/ecs/speaker/VoiceSystem.js +15 -9
  71. package/src/engine/ecs/terrain/ecs/TerrainClassifier.js +1 -1
  72. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +3 -3
  73. package/src/engine/ecs/terrain/ecs/splat/SplatMapOptimizerDebugger.js +3 -3
  74. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +2 -2
  75. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +2 -2
  76. package/src/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +2 -2
  77. package/src/engine/ecs/transform/Transform.js +1 -0
  78. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -4
  79. package/src/engine/graphics/copy_transform_to_threejs_object.js +12 -0
  80. package/src/engine/graphics/debug/VisualSymbolLine.js +1 -1
  81. package/src/engine/graphics/ecs/animation/animator/graph/AnimationGraph.spec.js +5 -0
  82. package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +24 -25
  83. package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.spec.js +5 -0
  84. package/src/engine/graphics/ecs/decal/DecalSystem.js +3 -21
  85. package/src/engine/graphics/ecs/decal/v2/Decal.js +32 -32
  86. package/src/engine/graphics/ecs/decal/v2/Decal.spec.js +5 -0
  87. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +4 -2
  88. package/src/engine/graphics/ecs/highlight/renderer/makeGaussianBlurShader.js +1 -4
  89. package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.d.ts +1 -1
  90. package/src/engine/graphics/ecs/highlight/system/RenderableHighlightSystem.js +2 -2
  91. package/src/engine/graphics/ecs/mesh/applyTransformToThreeObject.js +2 -5
  92. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +4 -33
  93. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +8 -4
  94. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.spec.js +5 -0
  95. package/src/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +0 -12
  96. package/src/engine/graphics/ecs/path/ribbon/RibbonPathBuilder.js +2 -2
  97. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
  98. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -4
  99. package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +0 -2
  100. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.js +1 -1
  101. package/src/engine/graphics/geometry/optimization/merge/prototypeGeometryMerge.js +1 -1
  102. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -3
  103. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -4
  104. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -5
  105. package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
  106. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +2 -6
  107. package/src/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +2 -1
  108. package/src/engine/graphics/sh3/path_tracer/PathTracer.js +6 -1
  109. package/src/engine/graphics/sh3/path_tracer/prototypePathTracer.js +4 -4
  110. package/src/engine/graphics/shaders/SoftOutlineShader.js +2 -4
  111. package/src/engine/graphics/shadows/testShadowMapRendering.js +0 -2
  112. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.spec.js +24 -0
  113. package/src/engine/graphics/texture/atlas/TextureAtlas.spec.js +46 -0
  114. package/src/engine/graphics/texture/sampler/SampleTraverser.js +1 -1
  115. package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
  116. package/src/engine/graphics/texture/sampler/bicubic.spec.js +13 -0
  117. package/src/engine/graphics/texture/sampler/differenceSampler.js +1 -1
  118. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_NaiveFlood.js +5 -1
  119. package/src/engine/graphics/texture/sampler/distance/computeSignedDistanceField_NaiveFlood.spec.js +183 -0
  120. package/src/engine/graphics/texture/sampler/filter/filter_lanczos3.js +20 -0
  121. package/src/engine/graphics/texture/sampler/filter/mitchell.js +0 -21
  122. package/src/engine/graphics/texture/sampler/filter/mitchell_v1.js +21 -0
  123. package/src/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +17 -16
  124. package/src/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +11 -9
  125. package/src/engine/graphics/texture/sampler/{scaleSampler2D.js → resize/sampler2d_scale.js} +8 -8
  126. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale.spec.js +73 -0
  127. package/src/engine/graphics/texture/sampler/{sampler2_d_scale_down_lanczos.js → resize/sampler2d_scale_down_lanczos.js} +3 -24
  128. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +29 -0
  129. package/src/engine/graphics/texture/sampler/{sampler2d_scale_down_linear.js → resize/sampler2d_scale_down_linear.js} +5 -5
  130. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.spec.js +44 -0
  131. package/src/engine/graphics/texture/sampler/resize/{sampler2d_downsample_mipmap.js → sampler2d_scale_down_mipmap.js} +2 -2
  132. package/src/engine/graphics/texture/sampler/resize/{sampler2d_downsample_mipmap.spec.js → sampler2d_scale_down_mipmap.spec.js} +2 -2
  133. package/src/engine/graphics/texture/sampler/{genericResampleSampler2D.js → resize/sampler2d_scale_generic.js} +16 -12
  134. package/src/engine/graphics/texture/sampler/{upsampleSampler2D.js → resize/sampler2d_scale_up_linear.js} +5 -2
  135. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_up_linear.spec.js +14 -0
  136. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min_indices.js +4 -2
  137. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min_indices.spec.js +15 -0
  138. package/src/engine/graphics/texture/sampler/util/drawSamplerHTML.js +2 -2
  139. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.js +46 -0
  140. package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.spec.js +108 -0
  141. package/src/engine/graphics/trail/TemporalPath.js +83 -78
  142. package/src/engine/graphics/trail/TemporalPath.spec.js +5 -0
  143. package/src/engine/graphics/trail/x/RibbonX.spec.js +5 -0
  144. package/src/engine/grid/components/GridObstacle.js +45 -25
  145. package/src/engine/grid/components/GridObstacle.spec.js +130 -1
  146. package/src/engine/grid/components/GridPosition.js +5 -17
  147. package/src/engine/grid/components/GridPosition2Transform.js +1 -70
  148. package/src/engine/grid/components/GridPosition2TransformSerializationAdapter.js +70 -0
  149. package/src/engine/input/devices/InputDeviceSwitch.spec.js +5 -0
  150. package/src/engine/input/ecs/{InputBinding.js → components/InputBinding.js} +1 -1
  151. package/src/engine/input/ecs/components/InputController.js +2 -2
  152. package/src/engine/input/ecs/ism/InputBinding.js +2 -2
  153. package/src/engine/input/ecs/util/TerrainCameraTargetSampler.js +1 -1
  154. package/src/engine/input/ecs/util/TopDownCameraControllerHelper.js +1 -1
  155. package/src/engine/intelligence/behavior/behavior_to_dot.spec.js +25 -0
  156. package/src/engine/intelligence/behavior/util/DelayBehavior.js +6 -4
  157. package/src/engine/intelligence/blackboard/Blackboard.d.ts +2 -0
  158. package/src/engine/intelligence/blackboard/Blackboard.js +36 -2
  159. package/src/engine/intelligence/blackboard/Blackboard.spec.js +49 -0
  160. package/src/engine/intelligence/blackboard/BlackboardSerializationAdapter.spec.js +2 -0
  161. package/src/engine/navigation/grid/{AStar.js → find_path_on_grid_astar.js} +21 -18
  162. package/src/engine/navigation/grid/find_path_on_grid_astar.spec.js +7 -0
  163. package/src/engine/plugin/EnginePlugin.js +12 -14
  164. package/src/engine/plugin/EnginePlugin.spec.js +5 -0
  165. package/src/engine/plugin/EnginePluginManager.js +18 -22
  166. package/src/engine/scene/transitionToScene.js +12 -1
  167. package/src/engine/simulation/Ticker.js +1 -1
  168. package/src/engine/sound/ecs/SoundListenerSystem.js +1 -1
  169. package/src/generation/markers/debug/visualizeMarkers.js +1 -1
  170. package/src/generation/theme/TerrainLayerDescription.js +1 -1
  171. package/src/view/common/LabelView.js +3 -3
  172. package/src/engine/MeepSettings.js +0 -9
  173. package/src/engine/User.js +0 -28
  174. package/src/engine/UserController.js +0 -273
  175. package/src/engine/ecs/components/AABB.js +0 -33
  176. package/src/engine/ecs/components/AABBCollider.js +0 -15
  177. package/src/engine/ecs/components/AimController.js +0 -18
  178. package/src/engine/ecs/components/Attacker.js +0 -13
  179. package/src/engine/ecs/components/MeshCollider.js +0 -15
  180. package/src/engine/ecs/components/RangedAttack.js +0 -12
  181. package/src/engine/ecs/components/Renderable.d.ts +0 -14
  182. package/src/engine/ecs/components/TargetAI.js +0 -11
  183. package/src/engine/ecs/components/ViewportMeshProjection.js +0 -18
  184. package/src/engine/ecs/grid/Sampler2DDecoder.js +0 -57
  185. package/src/engine/ecs/grid/makeTerrainGeometry.js +0 -110
  186. package/src/engine/ecs/systems/AABBColliderSystem.js +0 -61
  187. package/src/engine/ecs/systems/AABBSystem.js +0 -89
  188. package/src/engine/ecs/systems/AimControllerSystem.js +0 -63
  189. package/src/engine/ecs/systems/AttackerSystem.js +0 -67
  190. package/src/engine/ecs/systems/MeshColliderSystem.js +0 -47
  191. package/src/engine/ecs/systems/MonsterAISystem.js +0 -163
  192. package/src/engine/ecs/systems/MortalitySystem.js +0 -46
  193. package/src/engine/ecs/systems/RangedAttackSystem.js +0 -132
  194. package/src/engine/ecs/systems/SerializationMetadataSystem.js +0 -10
  195. package/src/engine/ecs/systems/TargetAISystem.js +0 -107
  196. package/src/engine/ecs/systems/ViewportMeshProjectionSystem.js +0 -68
  197. package/src/engine/graphics/particles/ParticleEmitterLibrary.js +0 -87
  198. package/src/engine/graphics/texture/sampler/sampler2d_make_array_filler_function.js +0 -65
  199. package/src/engine/graphics/texture/sampler/sampler2d_scale_down_linear.spec.js +0 -17
  200. package/src/engine/graphics/trail/x/simulator/RibbonState.js +0 -10
  201. package/src/engine/grid/Grid.js +0 -131
  202. package/src/engine/grid/components/ViewportGridProjection.js +0 -20
  203. package/src/engine/grid/systems/GridObstacleSystem.js +0 -58
  204. package/src/engine/grid/systems/ViewportGridProjectionSystem.js +0 -105
  205. package/src/engine/navigation/grid/GridField.js +0 -328
  206. /package/src/{engine → core/primitives/array}/computeStridedIntegerArrayHash.js +0 -0
  207. /package/src/engine/ecs/{components → renderable}/RenderableFlags.js +0 -0
@@ -0,0 +1,87 @@
1
+ import { sdnoise1, sdnoise2, sdnoise3, sdnoise4 } from "./sdnoise.js";
2
+
3
+ describe("sdnoise1", () => {
4
+ test("sanity", () => {
5
+ const derivatives = [];
6
+
7
+ const value = sdnoise1(derivatives, 0);
8
+
9
+ expect(typeof value).toBe("number");
10
+ expect(value).not.toBeNaN();
11
+
12
+ expect(derivatives.length).toEqual(1);
13
+
14
+ expect(typeof derivatives[0]).toBe("number");
15
+ expect(derivatives[0]).not.toBeNaN();
16
+
17
+ });
18
+ });
19
+
20
+ describe("sdnoise2", () => {
21
+ test("sanity", () => {
22
+ const derivatives = [];
23
+
24
+ const value = sdnoise2(derivatives, 0, 0);
25
+
26
+ expect(typeof value).toBe("number");
27
+ expect(value).not.toBeNaN();
28
+
29
+ expect(derivatives.length).toEqual(2);
30
+
31
+ expect(typeof derivatives[0]).toBe("number");
32
+ expect(derivatives[0]).not.toBeNaN();
33
+
34
+ expect(typeof derivatives[1]).toBe("number");
35
+ expect(derivatives[1]).not.toBeNaN();
36
+
37
+ });
38
+ });
39
+
40
+ describe("sdnoise3", () => {
41
+ test("sanity", () => {
42
+ const derivatives = [];
43
+
44
+ const value = sdnoise3(derivatives, 0, 0, 0);
45
+
46
+ expect(typeof value).toBe("number");
47
+ expect(value).not.toBeNaN();
48
+
49
+ expect(derivatives.length).toEqual(3);
50
+
51
+ expect(typeof derivatives[0]).toBe("number");
52
+ expect(derivatives[0]).not.toBeNaN();
53
+
54
+ expect(typeof derivatives[1]).toBe("number");
55
+ expect(derivatives[1]).not.toBeNaN();
56
+
57
+ expect(typeof derivatives[2]).toBe("number");
58
+ expect(derivatives[2]).not.toBeNaN();
59
+
60
+ });
61
+ });
62
+
63
+ describe("sdnoise4", () => {
64
+ test("sanity", () => {
65
+ const derivatives = [];
66
+
67
+ const value = sdnoise4(derivatives, 0, 0, 0, 0);
68
+
69
+ expect(typeof value).toBe("number");
70
+ expect(value).not.toBeNaN();
71
+
72
+ expect(derivatives.length).toEqual(4);
73
+
74
+ expect(typeof derivatives[0]).toBe("number");
75
+ expect(derivatives[0]).not.toBeNaN();
76
+
77
+ expect(typeof derivatives[1]).toBe("number");
78
+ expect(derivatives[1]).not.toBeNaN();
79
+
80
+ expect(typeof derivatives[2]).toBe("number");
81
+ expect(derivatives[2]).not.toBeNaN();
82
+
83
+ expect(typeof derivatives[3]).toBe("number");
84
+ expect(derivatives[3]).not.toBeNaN();
85
+
86
+ });
87
+ });
@@ -15,9 +15,7 @@ export class ModuleRegistry {
15
15
 
16
16
  constructor() {
17
17
 
18
- const self = this;
19
-
20
- this.proxy = new Proxy({}, {
18
+ this.proxy = new Proxy(this, {
21
19
  /**
22
20
  *
23
21
  * @param target
@@ -26,7 +24,7 @@ export class ModuleRegistry {
26
24
  * @returns {Class}
27
25
  */
28
26
  get(target, p, receiver) {
29
- const module = self.get(p);
27
+ const module = target.get(p);
30
28
 
31
29
  if (module === undefined) {
32
30
  throw new Error(`Module '${p}' not found in the registry`);
@@ -0,0 +1,31 @@
1
+ import { ModuleRegistry } from "./ModuleRegistry.js";
2
+
3
+ test("constructor does not throw", () => {
4
+
5
+ expect(() => new ModuleRegistry()).not.toThrow();
6
+
7
+ });
8
+
9
+ test("add/retrieve", () => {
10
+
11
+ const registry = new ModuleRegistry();
12
+
13
+ const module = {};
14
+
15
+ registry.add("x", module);
16
+
17
+ expect(registry.get("x")).toBe(module);
18
+
19
+ });
20
+
21
+ test("retrieve by proxy", () => {
22
+
23
+ const registry = new ModuleRegistry();
24
+
25
+ const module = {};
26
+
27
+ registry.add("x", module);
28
+
29
+ expect(registry.proxy.x).toBe(module);
30
+
31
+ });
@@ -0,0 +1,14 @@
1
+ import { compileReactiveToJS } from "./compileReactiveToJS.js";
2
+ import { ReactiveLiteralBoolean } from "../model/terminal/ReactiveLiteralBoolean.js";
3
+ import { ReactiveLiteralNumber } from "../model/terminal/ReactiveLiteralNumber.js";
4
+ import { ReactiveLiteralString } from "../model/terminal/ReactiveLiteralString.js";
5
+
6
+ test("literal expressions", () => {
7
+
8
+ expect(compileReactiveToJS(ReactiveLiteralBoolean.from(true))).toEqual("true");
9
+
10
+ expect(compileReactiveToJS(ReactiveLiteralNumber.from(13.1))).toEqual("13.1");
11
+
12
+ expect(compileReactiveToJS(ReactiveLiteralString.from("a"))).toEqual("'a'");
13
+
14
+ });
@@ -1,7 +1,7 @@
1
1
  import { ReactiveLiteralBoolean } from "../terminal/ReactiveLiteralBoolean.js";
2
2
  import { ReactiveAnd } from "./ReactiveAnd.js";
3
3
 
4
- test('.copy method must not change the original', () => {
4
+ test('copy method does not modify the sources', () => {
5
5
 
6
6
  const b0 = ReactiveLiteralBoolean.from(false);
7
7
  const b1 = ReactiveLiteralBoolean.from(true);
@@ -19,3 +19,33 @@ test('.copy method must not change the original', () => {
19
19
  expect(b1.getValue()).toBe(true);
20
20
 
21
21
  });
22
+
23
+ test("equals", () => {
24
+
25
+ const a = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
26
+ const b = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
27
+ const c = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
28
+ const d = ReactiveAnd.from(ReactiveLiteralBoolean.from(false), ReactiveLiteralBoolean.from(true));
29
+
30
+ expect(a.equals(b)).toBe(true);
31
+ expect(a.equals(c)).toBe(false);
32
+ expect(a.equals(d)).toBe(false);
33
+
34
+ expect(a.equals(ReactiveLiteralBoolean.from(true))).toBe(false);
35
+ });
36
+
37
+ test("evaluate", () => {
38
+ const a = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
39
+ const b = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
40
+
41
+ expect(a.evaluate({})).toBe(true);
42
+ expect(b.evaluate({})).toBe(false);
43
+ });
44
+
45
+ test("clone", () => {
46
+ const source = ReactiveAnd.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
47
+
48
+ const clone = source.clone();
49
+
50
+ expect(clone.equals(source)).toBe(true);
51
+ });
@@ -0,0 +1,53 @@
1
+ import { ReactiveLiteralBoolean } from "../terminal/ReactiveLiteralBoolean.js";
2
+ import { ReactiveOr } from "./ReactiveOr.js";
3
+
4
+ test('copy method does not modify the sources', () => {
5
+
6
+ const b0 = ReactiveLiteralBoolean.from(false);
7
+ const b1 = ReactiveLiteralBoolean.from(true);
8
+
9
+ const a = new ReactiveOr();
10
+
11
+
12
+ a.connect(b0, b1);
13
+
14
+ const b = new ReactiveOr();
15
+
16
+ b.copy(a);
17
+
18
+ expect(b0.getValue()).toBe(false);
19
+ expect(b1.getValue()).toBe(true);
20
+
21
+ });
22
+
23
+ test("equals", () => {
24
+
25
+ const a = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
26
+ const b = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
27
+ const c = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
28
+ const d = ReactiveOr.from(ReactiveLiteralBoolean.from(false), ReactiveLiteralBoolean.from(true));
29
+
30
+ expect(a.equals(b)).toBe(true);
31
+ expect(a.equals(c)).toBe(false);
32
+ expect(a.equals(d)).toBe(false);
33
+
34
+ expect(a.equals(ReactiveLiteralBoolean.from(true))).toBe(false);
35
+ });
36
+
37
+ test("evaluate", () => {
38
+ const a = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(true));
39
+ const b = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
40
+ const c = ReactiveOr.from(ReactiveLiteralBoolean.from(false), ReactiveLiteralBoolean.from(false));
41
+
42
+ expect(a.evaluate({})).toBe(true);
43
+ expect(b.evaluate({})).toBe(true);
44
+ expect(c.evaluate({})).toBe(false);
45
+ });
46
+
47
+ test("clone", () => {
48
+ const source = ReactiveOr.from(ReactiveLiteralBoolean.from(true), ReactiveLiteralBoolean.from(false));
49
+
50
+ const clone = source.clone();
51
+
52
+ expect(clone.equals(source)).toBe(true);
53
+ });
@@ -13,8 +13,8 @@ class LinearModifier {
13
13
  * @constructor
14
14
  */
15
15
  constructor(a = 1, b = 0) {
16
- assert.typeOf(a, 'number', 'a');
17
- assert.typeOf(b, 'number', 'b');
16
+ assert.isNumber(a, 'a');
17
+ assert.isNumber(b, 'b');
18
18
 
19
19
  /**
20
20
  * gradient (slope)
@@ -33,3 +33,65 @@ test("equals method", () => {
33
33
  expect(a.equals(c)).toBe(false);
34
34
  expect(a.equals(d)).toBe(false);
35
35
  });
36
+
37
+ test("hash", () => {
38
+ const mod = new LinearModifier(3, -7);
39
+
40
+ const hash = mod.hash();
41
+
42
+ expect(mod.hash()).toEqual(hash); // idempotency
43
+ expect(typeof hash).toEqual("number");
44
+ expect(Number.isInteger(hash)).toBe(true);
45
+ });
46
+
47
+ test("copy", () => {
48
+
49
+ const source = new LinearModifier(3, -7);
50
+ const target = new LinearModifier(1, 1);
51
+
52
+ target.copy(source);
53
+
54
+ expect(target.a).toBe(3);
55
+ expect(target.b).toBe(-7);
56
+
57
+ // check that original was not changed
58
+
59
+ expect(source.a).toBe(3);
60
+ expect(source.b).toBe(-7);
61
+ });
62
+
63
+ test("clone", () => {
64
+
65
+ const source = new LinearModifier(3, -7);
66
+
67
+ const clone = source.clone();
68
+
69
+ expect(clone.equals(source)).toBe(true);
70
+
71
+ });
72
+
73
+ test("to/from JSON consistency", () => {
74
+
75
+ const source = new LinearModifier(3, -7);
76
+ const target = new LinearModifier(1, 1);
77
+
78
+ target.fromJSON(source.toJSON());
79
+
80
+ expect(target.a).toBe(3);
81
+ expect(target.b).toBe(-7);
82
+
83
+ // check that original was not changed
84
+
85
+ expect(source.a).toBe(3);
86
+ expect(source.b).toBe(-7);
87
+ });
88
+
89
+ test("toString produces a valid string", () => {
90
+
91
+ const s = new LinearModifier(3, -7).toString();
92
+
93
+ expect(typeof s).toBe("string");
94
+ expect(s.trim().length).toBeGreaterThan(0);
95
+
96
+ });
97
+
@@ -140,6 +140,15 @@ class Stat extends Number {
140
140
  this.updateValue();
141
141
  }
142
142
 
143
+ /**
144
+ *
145
+ * @param {LinearModifier} mod
146
+ * @return {boolean}
147
+ */
148
+ hasModifier(mod) {
149
+ return this.__modifiers.contains(mod);
150
+ }
151
+
143
152
  /**
144
153
  *
145
154
  * @param {LinearModifier} mod
@@ -174,6 +183,8 @@ class Stat extends Number {
174
183
  copy(other) {
175
184
  this.base.copy(other.base);
176
185
  this.__modifiers.copy(other.__modifiers);
186
+
187
+ this.updateValue();
177
188
  }
178
189
 
179
190
  /**
@@ -226,6 +237,7 @@ class Stat extends Number {
226
237
  fromJSON(json) {
227
238
  this.base.fromJSON(json.base);
228
239
  this.__modifiers.fromJSON(json.modifiers, LinearModifier);
240
+ this.updateValue();
229
241
  }
230
242
 
231
243
  /**
@@ -73,3 +73,39 @@ test("order of modifiers doesn't matter", () => {
73
73
  expect(s.getValue()).toEqual(-45);
74
74
  }
75
75
  });
76
+
77
+ test("toString produces a valid string", () => {
78
+ const stat = new Stat(1);
79
+
80
+ const s = stat.toString();
81
+
82
+ expect(typeof s).toBe("string");
83
+ expect(s.trim().length).toBeGreaterThan(0);
84
+ });
85
+
86
+ test("copy", () => {
87
+ const source = new Stat(7);
88
+
89
+ source.addModifier(LinearModifier.CONSTANT_ONE);
90
+
91
+ const other = new Stat(1);
92
+
93
+ other.copy(source);
94
+
95
+ expect(other.getBaseValue()).toBe(7);
96
+ expect(other.hasModifier(LinearModifier.CONSTANT_ONE));
97
+
98
+ expect(other.equals(source)).toBe(true);
99
+ });
100
+
101
+ test("to/from JSON consistency", () => {
102
+
103
+ const source = new Stat(7);
104
+ source.addModifier(LinearModifier.CONSTANT_ONE);
105
+
106
+ const destination = new Stat(1);
107
+
108
+ destination.fromJSON(source.toJSON());
109
+
110
+ expect(destination.equals(source)).toBe(true);
111
+ });
@@ -0,0 +1,28 @@
1
+ import { computeStridedIntegerArrayHash } from "./computeStridedIntegerArrayHash.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number[]} value
6
+ * @param {number} [stride]
7
+ */
8
+ function check(value, stride = 1) {
9
+ const hash = computeStridedIntegerArrayHash(value, 0, value.length, 1);
10
+
11
+ expect(typeof hash).toBe('number');
12
+ expect(Number.isInteger(hash)).toBe(true);
13
+
14
+ }
15
+
16
+ test("sanity", () => {
17
+
18
+ check([], 1);
19
+
20
+ check([1], 1);
21
+ check([1], 3);
22
+
23
+ check([1, 3], 1);
24
+ check([1, 3], 3);
25
+
26
+ check([1, 3, 7], 3);
27
+
28
+ });
@@ -0,0 +1,14 @@
1
+ import { assert } from "../../assert.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number} x
6
+ * @param {string} [separator=',']
7
+ * @returns {string}
8
+ */
9
+ export function number_format_by_thousands(x, separator = ',') {
10
+ assert.isNumber(x, 'x');
11
+ assert.isString(separator, 'separator');
12
+
13
+ return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator);
14
+ }
@@ -0,0 +1,49 @@
1
+ import { assert } from "../../assert.js";
2
+ import { number_format_by_thousands } from "./number_format_by_thousands.js";
3
+
4
+ /**
5
+ *
6
+ * @param {string} value
7
+ * @returns {number}
8
+ */
9
+ function countDecimals(value) {
10
+ if (value % 1 === 0) {
11
+ //whole number
12
+ return 0;
13
+ }
14
+ const s = value.toString();
15
+ const index = s.indexOf('.');
16
+
17
+ if (index === -1) {
18
+ return 0;
19
+ }
20
+
21
+ //find last 0
22
+ let endIndex = s.length - 1;
23
+ for (; endIndex > index && s.charAt(endIndex) === "0"; endIndex--) {
24
+
25
+ }
26
+ return endIndex - index;
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param {number} value
32
+ * @returns {string|number}
33
+ */
34
+ export function number_pretty_print(value) {
35
+ assert.isNumber(value, 'value');
36
+
37
+ const MAX_DECIMALS = 2;
38
+
39
+ const fraction = value % 1;
40
+ if (fraction !== 0 && Math.abs(value) < 100) {
41
+ const decimals = countDecimals(value.toFixed(MAX_DECIMALS));
42
+ const decimalsToPrint = Math.min(decimals, MAX_DECIMALS);
43
+ return value.toFixed(decimalsToPrint);
44
+ } else {
45
+ //no fraction
46
+ return number_format_by_thousands(value - fraction, ",");
47
+ }
48
+
49
+ }
@@ -1,13 +1,20 @@
1
1
  import { computeStringHash } from "./computeStringHash.js";
2
2
 
3
- test('hash', () => {
3
+ function check(value) {
4
4
  // must produce a number
5
- expect(typeof computeStringHash('')).toBe('number');
5
+ const hash = computeStringHash(value);
6
+ expect(typeof hash).toBe('number');
7
+ expect(Number.isInteger(hash)).toBe(true);
8
+ expect(computeStringHash(value)).toEqual(hash); // stability
9
+ }
6
10
 
7
- // check for identical results from identical inputs
8
- expect(computeStringHash('')).toBe(computeStringHash(''));
11
+ test('hash', () => {
9
12
 
10
- expect(computeStringHash('cat')).toBe(computeStringHash('cat'));
13
+ check('');
14
+ check('cat');
15
+ check('tomato');
16
+ check(null);
17
+ check(undefined);
11
18
 
12
19
  expect(computeStringHash('tomato')).not.toBe(computeStringHash('potato'));
13
20
  });
@@ -4,14 +4,14 @@ import ObservedEnum from "../model/ObservedEnum.js";
4
4
  import { ProcessState } from "./ProcessState.js";
5
5
 
6
6
  export class BaseProcess {
7
- constructor() {
8
- this.id = "";
9
- /**
10
- * @readonly
11
- * @type {ObservedEnum.<ProcessState>}
12
- */
13
- this.__state = new ObservedEnum(ProcessState.New, ProcessState);
14
- }
7
+
8
+ id = "";
9
+ /**
10
+ * @readonly
11
+ * @type {ObservedEnum.<ProcessState>}
12
+ */
13
+ __state = new ObservedEnum(ProcessState.New, ProcessState);
14
+
15
15
 
16
16
  /**
17
17
  * @returns {ObservedEnum<ProcessState>}
@@ -5,16 +5,15 @@
5
5
 
6
6
  import Stat from "../core/model/stat/Stat.js";
7
7
 
8
+ //Use highest available resolution time source
9
+ const source = typeof performance === "undefined" ? Date : performance;
8
10
 
9
11
  /**
10
12
  *
11
13
  * @returns {number}
12
14
  */
13
15
  export function currentTimeInSeconds() {
14
- //Use highest available resolution time source
15
- const source = typeof performance === "undefined" ? Date : performance;
16
-
17
- return source.now() / 1000;
16
+ return source.now() * 0.001;
18
17
  }
19
18
 
20
19
  /**
@@ -29,35 +28,37 @@ function updateElapsedTime(clock) {
29
28
  }
30
29
 
31
30
  class Clock {
32
- constructor() {
33
- /**
34
- *
35
- * @type {number}
36
- * @private
37
- */
38
- this.__lastMeasurement = 0;
39
-
40
- /**
41
- *
42
- * @type {number}
43
- */
44
- this.elapsedTime = 0;
45
31
 
46
- this.timeAtDelta = 0;
32
+ /**
33
+ *
34
+ * @type {number}
35
+ * @private
36
+ */
37
+ __lastMeasurement = 0;
47
38
 
48
- /**
49
- *
50
- * @type {boolean}
51
- * @private
52
- */
53
- this.__isRunning = false;
39
+ /**
40
+ *
41
+ * @type {number}
42
+ */
43
+ elapsedTime = 0;
44
+
45
+ timeAtDelta = 0;
46
+
47
+ /**
48
+ *
49
+ * @type {boolean}
50
+ * @private
51
+ */
52
+ __isRunning = false;
54
53
 
55
54
 
56
- /**
57
- * how fast clock ticks in relation to real time
58
- * @type {Stat}
59
- */
60
- this.speed = new Stat(1);
55
+ /**
56
+ * how fast clock ticks in relation to real time
57
+ * @type {Stat}
58
+ */
59
+ speed = new Stat(1);
60
+
61
+ constructor() {
61
62
  this.speed.postprocess = Stat.Process.clampMin(0);
62
63
  }
63
64
 
@@ -0,0 +1,26 @@
1
+ import Clock from "./Clock.js";
2
+ import { delay } from "../core/process/delay.js";
3
+
4
+ test("constructor does not throw", () => {
5
+ new Clock();
6
+ });
7
+
8
+ test("reset", () => {
9
+ const clock = new Clock();
10
+ clock.reset();
11
+
12
+ expect(clock.getElapsedTime()).toBe(0);
13
+ expect(clock.getDelta()).toBe(0);
14
+ });
15
+
16
+ test("getDelta", async () => {
17
+ const clock = new Clock();
18
+
19
+ clock.start();
20
+
21
+ await delay(30);
22
+
23
+ const delta = clock.getDelta();
24
+
25
+ expect(delta).toBeCloseTo(0.03, 0.01);
26
+ });
@@ -4,7 +4,7 @@ let cached = null;
4
4
  * https://stackoverflow.com/questions/5916900/how-can-you-detect-the-version-of-a-browser
5
5
  * @returns {{name:String, version:Number}}
6
6
  */
7
- function browserInfo() {
7
+ export function browserInfo() {
8
8
  if (cached !== null) {
9
9
  return cached;
10
10
  }
@@ -46,7 +46,3 @@ function browserInfo() {
46
46
 
47
47
  return result;
48
48
  }
49
-
50
- export {
51
- browserInfo
52
- }