@woosh/meep-engine 2.51.0 → 2.53.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.
- package/editor/actions/concrete/WriteGridValueAction.js +1 -1
- package/editor/ecs/component/prototypeObjectEditor.js +1 -1
- package/editor/process/ObstacleGridDisplayProcess.js +2 -2
- package/editor/process/symbolic/makeGridPositionSymbolDisplay.js +1 -1
- package/editor/tools/GridPaintTool.js +2 -2
- package/package.json +4 -3
- package/samples/generation/SampleGenerator0.js +1 -1
- package/samples/generation/generators/interactive/mir_generator_place_buff_objects.js +1 -1
- package/samples/generation/generators/mir_generator_place_bases.js +1 -1
- package/samples/generation/generators/mir_generator_place_road_decorators.js +1 -1
- package/samples/generation/generators/mir_generator_place_starting_point.js +1 -1
- package/samples/generation/main.js +2 -2
- package/samples/generation/rules/matcher_play_area.js +1 -1
- package/samples/generation/rules/matcher_tag_occupied.js +1 -1
- package/samples/generation/rules/matcher_tag_traversable.js +1 -1
- package/samples/generation/themes/SampleTheme0.js +5 -5
- package/src/core/NumberFormat.js +0 -71
- package/src/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +1 -0
- package/src/core/bvh2/bvh3/query/BVHQueryAny.js +16 -0
- package/src/core/bvh2/bvh3/query/bvh_collect_user_data.js +5 -5
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.js +2 -3
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_generic.spec.js +22 -0
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +2 -2
- package/src/core/bvh2/bvh3/query/bvh_query_leaves_ray.spec.js +64 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_generic.js +2 -3
- package/src/core/collection/table/RowFirstTableSpec.js +8 -4
- package/src/core/geom/3d/aabb/aabb3_from_threejs_geometry.js +41 -0
- package/src/core/geom/3d/matrix/MATRIX_4_IDENTITY.spec.js +10 -0
- package/src/core/geom/3d/topology/struct/TopoMesh.js +3 -2
- package/src/core/geom/3d/topology/struct/prototypeBinaryTopology.js +4 -4
- package/src/core/geom/Vector2.d.ts +9 -0
- package/src/core/geom/Vector2.js +8 -22
- package/src/core/geom/Vector2.spec.js +153 -0
- package/src/core/model/ModuleRegistry.js +2 -4
- package/src/core/model/ModuleRegistry.spec.js +31 -0
- package/src/core/model/reactive/js/compileReactiveToJS.spec.js +14 -0
- package/src/core/model/reactive/model/logic/ReactiveAnd.spec.js +31 -1
- package/src/core/model/reactive/model/logic/ReactiveOr.spec.js +53 -0
- package/src/core/model/stat/LinearModifier.js +2 -2
- package/src/core/model/stat/LinearModifier.spec.js +62 -0
- package/src/core/model/stat/Stat.js +12 -0
- package/src/core/model/stat/Stat.spec.js +36 -0
- package/src/core/primitives/array/computeStridedIntegerArrayHash.spec.js +28 -0
- package/src/core/primitives/numbers/number_format_by_thousands.js +14 -0
- package/src/core/primitives/numbers/number_pretty_print.js +49 -0
- package/src/core/primitives/strings/computeStringHash.spec.js +12 -5
- package/src/core/process/BaseProcess.js +8 -8
- package/src/engine/Clock.js +30 -29
- package/src/engine/Clock.spec.js +26 -0
- package/src/engine/Engine.spec.js +4 -0
- package/src/engine/ecs/EntityBuilder.js +3 -1
- package/src/engine/ecs/EntityBuilder.spec.js +21 -0
- package/src/engine/ecs/EntityComponentDataset.js +1 -1
- package/src/engine/ecs/EntityObserver.spec.js +1 -1
- package/src/engine/ecs/dynamic_actions/actions/definition/{WhiteToBlackboardActionDescription.js → WriteToBlackboardActionDescription.js} +2 -2
- package/src/engine/ecs/dynamic_actions/actions/definition/deserializeActionFromJSON.js +2 -2
- package/src/engine/ecs/gui/GUIElement.js +1 -1
- package/src/engine/ecs/gui/position/ViewportPosition.js +3 -3
- package/src/engine/ecs/guid/GUIDSerializationAdapter.spec.js +21 -0
- package/src/engine/ecs/parent/EntityNode.js +1 -1
- package/src/engine/ecs/parent/EntityNode.spec.js +104 -0
- package/src/engine/ecs/speaker/Voice.js +4 -0
- package/src/engine/ecs/team/Team.js +0 -44
- package/src/engine/ecs/team/TeamSerializationAdapter.js +46 -0
- package/src/engine/ecs/terrain/ecs/TerrainClassifier.js +1 -1
- package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +1 -1
- package/src/engine/ecs/transform/Transform.js +2 -1
- package/src/engine/ecs/transform/Transform.spec.js +24 -0
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +2 -6
- package/src/engine/graphics/ecs/animation/animator/graph/AnimationGraph.spec.js +5 -0
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +24 -25
- package/src/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.spec.js +5 -0
- package/src/engine/graphics/ecs/decal/DecalSystem.js +2 -20
- package/src/engine/graphics/ecs/decal/v2/Decal.js +32 -32
- package/src/engine/graphics/ecs/decal/v2/Decal.spec.js +5 -0
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +4 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +4 -33
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +8 -4
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.spec.js +5 -0
- package/src/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +0 -12
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +2 -6
- package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +2 -4
- package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.js +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +0 -2
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +2 -6
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +2 -6
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +4 -8
- package/src/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +2 -1
- package/src/engine/graphics/sh3/path_tracer/PathTracer.js +6 -1
- package/src/engine/graphics/sh3/path_tracer/prototypePathTracer.js +2 -2
- package/src/engine/graphics/shadows/testShadowMapRendering.js +0 -2
- package/src/engine/graphics/texture/TextureBackedMemoryRegion.js +4 -1
- package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
- package/src/engine/graphics/texture/sampler/filter/filter_lanczos3.js +7 -2
- package/src/engine/graphics/three/expand_aabb_by_transformed_three_object.js +3 -23
- package/src/engine/grid/grid2transform/GridPosition2Transform.js +122 -0
- package/src/engine/grid/grid2transform/GridPosition2TransformSerializationAdapter.js +70 -0
- package/src/engine/grid/grid2transform/GridPosition2TransformSerializationUpgrader_0_1.js +40 -0
- package/src/engine/grid/{systems → grid2transform}/GridPosition2TransformSystem.js +3 -3
- package/src/engine/grid/{components → obstacle}/GridObstacle.js +45 -25
- package/src/engine/grid/obstacle/GridObstacle.spec.js +175 -0
- package/src/engine/grid/{components → position}/GridPosition.js +6 -14
- package/src/engine/grid/{systems → position}/GridPositionSystem.js +1 -1
- package/src/engine/grid/transform2grid/Transform2GridPositionSystem.js +1 -1
- package/src/engine/input/devices/PointerDevice.spec.js +5 -0
- package/src/engine/navigation/ecs/components/computeCatmullRomSpline.js +5 -1
- package/src/engine/navigation/ecs/path_following/PathFollower.js +40 -32
- package/src/engine/navigation/ecs/path_following/PathFollower.spec.js +27 -0
- package/src/engine/plugin/EnginePlugin.js +12 -14
- package/src/engine/plugin/EnginePlugin.spec.js +5 -0
- package/src/engine/plugin/EnginePluginManager.js +18 -22
- package/src/engine/scene/transitionToScene.js +12 -1
- package/src/engine/simulation/Ticker.js +1 -1
- package/src/generation/filtering/CellFilter.js +6 -9
- package/src/generation/filtering/boolean/CellFilterLiteralBoolean.js +1 -4
- package/src/generation/filtering/core/CellFilterBinaryOperation.js +12 -15
- package/src/generation/filtering/core/CellFilterOperationTertiary.js +15 -19
- package/src/generation/filtering/numeric/CellFilterLiteralFloat.js +6 -9
- package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.js +1 -1
- package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.js +2 -2
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +1 -1
- package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +1 -1
- package/src/generation/theme/TerrainLayerDescription.js +1 -1
- package/src/view/common/LabelView.js +3 -3
- package/src/engine/ecs/components/AimController.js +0 -18
- package/src/engine/ecs/components/Attacker.js +0 -13
- package/src/engine/ecs/components/MeshCollider.js +0 -15
- package/src/engine/ecs/components/RangedAttack.js +0 -12
- package/src/engine/ecs/components/TargetAI.js +0 -11
- package/src/engine/ecs/components/ViewportMeshProjection.js +0 -18
- package/src/engine/ecs/systems/AimControllerSystem.js +0 -63
- package/src/engine/ecs/systems/AttackerSystem.js +0 -67
- package/src/engine/ecs/systems/MeshColliderSystem.js +0 -47
- package/src/engine/ecs/systems/MonsterAISystem.js +0 -163
- package/src/engine/ecs/systems/MortalitySystem.js +0 -46
- package/src/engine/ecs/systems/RangedAttackSystem.js +0 -132
- package/src/engine/ecs/systems/SerializationMetadataSystem.js +0 -10
- package/src/engine/ecs/systems/TargetAISystem.js +0 -107
- package/src/engine/ecs/systems/ViewportMeshProjectionSystem.js +0 -68
- package/src/engine/graphics/particles/ParticleEmitterLibrary.js +0 -87
- package/src/engine/graphics/texture/ExportCanvasAsPNG.js +0 -7
- package/src/engine/grid/components/GridObstacle.spec.js +0 -46
- package/src/engine/grid/components/GridPosition2Transform.js +0 -232
- package/src/engine/grid/components/ViewportGridProjection.js +0 -20
- package/src/engine/grid/systems/GridObstacleSystem.js +0 -58
- package/src/engine/grid/systems/ViewportGridProjectionSystem.js +0 -105
- package/src/engine/navigation/PathFinder.js +0 -172
- package/src/engine/navigation/PathWorker.js +0 -78
- package/src/engine/navigation/ecs/systems/PathFinderSystem.js +0 -63
- package/src/engine/navigation/ecs/systems/PathSystem.js +0 -19
- package/src/engine/navigation/funnel/Funnel.js +0 -196
- package/src/generation/ZoneNode.js +0 -9
- /package/{src/generation → samples/generation/grid}/GridTags.js +0 -0
- /package/src/{engine → core/primitives/array}/computeStridedIntegerArrayHash.js +0 -0
- /package/src/engine/grid/{components → grid2transform}/GridPosition2TransformFlags.js +0 -0
- /package/src/engine/grid/{components → obstacle}/GridObstacleSerializationAdapter.js +0 -0
- /package/src/engine/grid/{components → position}/GridPositionSerializationAdapter.js +0 -0
- /package/src/engine/grid/{components → position}/GridPositionSerializationUpdater_0_1.js +0 -0
package/src/core/geom/Vector2.js
CHANGED
|
@@ -450,7 +450,10 @@ class Vector2 {
|
|
|
450
450
|
* @param {number} fraction
|
|
451
451
|
*/
|
|
452
452
|
lerpVectors(a, b, fraction) {
|
|
453
|
-
|
|
453
|
+
const x = lerp(a.x, b.x, fraction);
|
|
454
|
+
const y = lerp(a.y, b.y, fraction);
|
|
455
|
+
|
|
456
|
+
this.set(x, y);
|
|
454
457
|
}
|
|
455
458
|
|
|
456
459
|
/**
|
|
@@ -538,7 +541,7 @@ class Vector2 {
|
|
|
538
541
|
*
|
|
539
542
|
* @returns {number}
|
|
540
543
|
*/
|
|
541
|
-
|
|
544
|
+
hash() {
|
|
542
545
|
const x = Math.sin(this.x) * 1367130550;
|
|
543
546
|
const y = Math.sin(this.y) * 1367130550;
|
|
544
547
|
|
|
@@ -550,7 +553,7 @@ class Vector2 {
|
|
|
550
553
|
}
|
|
551
554
|
|
|
552
555
|
/**
|
|
553
|
-
*
|
|
556
|
+
* Rotation is counter-clockwise
|
|
554
557
|
* @param {number} angle in radians
|
|
555
558
|
*/
|
|
556
559
|
rotate(angle) {
|
|
@@ -558,7 +561,7 @@ class Vector2 {
|
|
|
558
561
|
const cos = Math.cos(angle);
|
|
559
562
|
|
|
560
563
|
const x = this.x * cos - this.y * sin
|
|
561
|
-
const y = this.x * sin
|
|
564
|
+
const y = this.x * sin + this.y * cos;
|
|
562
565
|
|
|
563
566
|
this.set(x, y);
|
|
564
567
|
}
|
|
@@ -597,7 +600,7 @@ class Vector2 {
|
|
|
597
600
|
* @return {boolean}
|
|
598
601
|
*/
|
|
599
602
|
roughlyEquals(other, tolerance) {
|
|
600
|
-
return this._roughlyEquals(other.x, other.y,
|
|
603
|
+
return this._roughlyEquals(other.x, other.y, tolerance);
|
|
601
604
|
}
|
|
602
605
|
|
|
603
606
|
/**
|
|
@@ -677,23 +680,6 @@ Vector2.one = Object.freeze(new Vector2(1, 1));
|
|
|
677
680
|
* @type {boolean}
|
|
678
681
|
*/
|
|
679
682
|
Vector2.prototype.isVector2 = true;
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
*
|
|
683
|
-
* @param {Vector2} result
|
|
684
|
-
* @param {Vector2} a
|
|
685
|
-
* @param {Vector2} b
|
|
686
|
-
* @param {number} fraction
|
|
687
|
-
*/
|
|
688
|
-
function v2Lerp(result, a, b, fraction) {
|
|
689
|
-
|
|
690
|
-
const x = lerp(a.x, b.x, fraction);
|
|
691
|
-
const y = lerp(a.y, b.y, fraction);
|
|
692
|
-
|
|
693
|
-
result.set(x, y);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
|
|
697
683
|
/**
|
|
698
684
|
*
|
|
699
685
|
* @param {number} x0
|
|
@@ -8,6 +8,21 @@ test("setting x and y via constructor", () => {
|
|
|
8
8
|
expect(v.y).toBe(13);
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
test("array-style accessors", () => {
|
|
12
|
+
|
|
13
|
+
const v = new Vector2();
|
|
14
|
+
|
|
15
|
+
v[0] = 3;
|
|
16
|
+
v[1] = -7;
|
|
17
|
+
|
|
18
|
+
expect(v[0]).toEqual(3);
|
|
19
|
+
expect(v.x).toEqual(3);
|
|
20
|
+
|
|
21
|
+
expect(v[1]).toEqual(-7);
|
|
22
|
+
expect(v.y).toEqual(-7);
|
|
23
|
+
|
|
24
|
+
});
|
|
25
|
+
|
|
11
26
|
test('add works', () => {
|
|
12
27
|
const a = new Vector2(1, 3);
|
|
13
28
|
const b = new Vector2(5, 7);
|
|
@@ -140,3 +155,141 @@ test("onChange is dispatched when y changes via set", () => {
|
|
|
140
155
|
|
|
141
156
|
expect(changeHandler).toHaveBeenLastCalledWith(2, 3, 1, 3);
|
|
142
157
|
});
|
|
158
|
+
|
|
159
|
+
test("rotate", () => {
|
|
160
|
+
|
|
161
|
+
const v = new Vector2(0, 0);
|
|
162
|
+
|
|
163
|
+
v.rotate(0);
|
|
164
|
+
|
|
165
|
+
expect(v.x).toBeCloseTo(0);
|
|
166
|
+
expect(v.y).toBeCloseTo(0);
|
|
167
|
+
|
|
168
|
+
v.set(1, 0);
|
|
169
|
+
|
|
170
|
+
v.rotate(0);
|
|
171
|
+
|
|
172
|
+
expect(v.x).toBeCloseTo(1);
|
|
173
|
+
expect(v.y).toBeCloseTo(0);
|
|
174
|
+
|
|
175
|
+
v.set(0, 1);
|
|
176
|
+
|
|
177
|
+
v.rotate(0);
|
|
178
|
+
|
|
179
|
+
expect(v.x).toBeCloseTo(0);
|
|
180
|
+
expect(v.y).toBeCloseTo(1);
|
|
181
|
+
|
|
182
|
+
v.set(1, 0);
|
|
183
|
+
|
|
184
|
+
v.rotate(Math.PI);
|
|
185
|
+
|
|
186
|
+
expect(v.x).toBeCloseTo(-1);
|
|
187
|
+
expect(v.y).toBeCloseTo(0);
|
|
188
|
+
|
|
189
|
+
v.set(-1, 0);
|
|
190
|
+
|
|
191
|
+
v.rotate(Math.PI);
|
|
192
|
+
|
|
193
|
+
expect(v.x).toBeCloseTo(1);
|
|
194
|
+
expect(v.y).toBeCloseTo(0);
|
|
195
|
+
|
|
196
|
+
v.set(0, 1);
|
|
197
|
+
|
|
198
|
+
v.rotate(Math.PI);
|
|
199
|
+
|
|
200
|
+
expect(v.x).toBeCloseTo(0);
|
|
201
|
+
expect(v.y).toBeCloseTo(-1);
|
|
202
|
+
|
|
203
|
+
v.set(0, -1);
|
|
204
|
+
|
|
205
|
+
v.rotate(Math.PI);
|
|
206
|
+
|
|
207
|
+
expect(v.x).toBeCloseTo(0);
|
|
208
|
+
expect(v.y).toBeCloseTo(1);
|
|
209
|
+
|
|
210
|
+
v.set(1, 1);
|
|
211
|
+
|
|
212
|
+
v.rotate(Math.PI * 0.5);
|
|
213
|
+
|
|
214
|
+
expect(v.x).toBeCloseTo(-1);
|
|
215
|
+
expect(v.y).toBeCloseTo(1);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test("hash", () => {
|
|
219
|
+
|
|
220
|
+
function validate(x, y) {
|
|
221
|
+
|
|
222
|
+
const v = new Vector2(x, y);
|
|
223
|
+
|
|
224
|
+
const hash = v.hash();
|
|
225
|
+
|
|
226
|
+
expect(hash).toEqual(v.hash()); // stability
|
|
227
|
+
expect(typeof hash).toBe("number");
|
|
228
|
+
expect(Number.isInteger(hash)).toBe(true);
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
validate(0, 0);
|
|
233
|
+
validate(0, 1);
|
|
234
|
+
validate(1, 0);
|
|
235
|
+
validate(1, 1);
|
|
236
|
+
|
|
237
|
+
validate(0, -1);
|
|
238
|
+
validate(-1, 0);
|
|
239
|
+
validate(-1, -1);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("normalize", () => {
|
|
243
|
+
|
|
244
|
+
const v = new Vector2(1, 1);
|
|
245
|
+
|
|
246
|
+
v.normalize();
|
|
247
|
+
|
|
248
|
+
const s = 1 / Math.SQRT2;
|
|
249
|
+
|
|
250
|
+
expect(v.x).toBeCloseTo(s);
|
|
251
|
+
expect(v.y).toBeCloseTo(s);
|
|
252
|
+
|
|
253
|
+
v.set(-1, -1);
|
|
254
|
+
|
|
255
|
+
v.normalize();
|
|
256
|
+
|
|
257
|
+
expect(v.x).toBeCloseTo(-s);
|
|
258
|
+
expect(v.y).toBeCloseTo(-s);
|
|
259
|
+
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("length", () => {
|
|
263
|
+
|
|
264
|
+
expect(new Vector2(1, 0).length()).toBeCloseTo(1);
|
|
265
|
+
expect(new Vector2(0, 1).length()).toBeCloseTo(1);
|
|
266
|
+
|
|
267
|
+
expect(new Vector2(1, 1).length()).toBeCloseTo(Math.SQRT2);
|
|
268
|
+
|
|
269
|
+
expect(new Vector2(-1, 1).length()).toBeCloseTo(Math.SQRT2);
|
|
270
|
+
|
|
271
|
+
expect(new Vector2(1, -1).length()).toBeCloseTo(Math.SQRT2);
|
|
272
|
+
|
|
273
|
+
expect(new Vector2(-1, -1).length()).toBeCloseTo(Math.SQRT2);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
test("manhattanDistanceTo", () => {
|
|
278
|
+
const a = new Vector2(1, 3);
|
|
279
|
+
const b = new Vector2(5, 11);
|
|
280
|
+
|
|
281
|
+
expect(a.manhattanDistanceTo(b)).toEqual(12)
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("lerpVectors", () => {
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
const a = new Vector2(-1, 3);
|
|
288
|
+
const b = new Vector2(5, -11);
|
|
289
|
+
|
|
290
|
+
a.lerpVectors(a, b, 0.1);
|
|
291
|
+
|
|
292
|
+
expect(a.x).toBeCloseTo(-1 * 0.9 + 5 * 0.1);
|
|
293
|
+
expect(a.y).toBeCloseTo(3 * 0.9 - 11 * 0.1);
|
|
294
|
+
|
|
295
|
+
});
|
|
@@ -15,9 +15,7 @@ export class ModuleRegistry {
|
|
|
15
15
|
|
|
16
16
|
constructor() {
|
|
17
17
|
|
|
18
|
-
|
|
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 =
|
|
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('
|
|
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
|
+
});
|
|
@@ -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
|
-
|
|
3
|
+
function check(value) {
|
|
4
4
|
// must produce a number
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
expect(computeStringHash('')).toBe(computeStringHash(''));
|
|
11
|
+
test('hash', () => {
|
|
9
12
|
|
|
10
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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>}
|