Skip to content

Commit ea3c11b

Browse files
committed
add test capture sort to improve comparison
1 parent de04c00 commit ea3c11b

2 files changed

Lines changed: 111 additions & 106 deletions

File tree

test/ExampleWorker.js

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,27 @@
33
"use strict";
44

55
const mock = require('mock-require');
6-
const { requireUncached, engineCapture } = require('./TestTools');
76
const Example = require('../examples/index');
7+
const { requireUncached } = require('./TestTools');
88
const consoleOriginal = global.console;
99

10+
const intrinsicProps = [
11+
// Common
12+
'id', 'label',
13+
14+
// Constraint
15+
'angularStiffness', 'bodyA', 'bodyB', 'damping', 'length', 'stiffness',
16+
17+
// Body
18+
'area', 'axes', 'collisionFilter', 'category', 'mask',
19+
'group', 'density', 'friction', 'frictionAir', 'frictionStatic', 'inertia', 'inverseInertia', 'inverseMass', 'isSensor',
20+
'isSleeping', 'isStatic', 'mass', 'parent', 'parts', 'restitution', 'sleepThreshold', 'slop',
21+
'timeScale', 'vertices',
22+
23+
// Composite
24+
'bodies', 'constraints', 'composites'
25+
];
26+
1027
const prepareMatter = (options) => {
1128
const Matter = requireUncached(options.useDev ? '../build/matter.dev' : '../build/matter');
1229

@@ -48,6 +65,97 @@ const resetEnvironment = () => {
4865
mock.stopAll();
4966
};
5067

68+
const limitPrecision = (val, precision=3) => parseFloat(val.toPrecision(precision));
69+
70+
const sortById = (objs) => {
71+
objs.sort((objA, objB) => objA.id - objB.id);
72+
return objs;
73+
};
74+
75+
const engineCapture = (engine, Matter) => ({
76+
timestamp: limitPrecision(engine.timing.timestamp),
77+
extrinsic: worldCaptureExtrinsic(engine.world, Matter),
78+
intrinsic: worldCaptureIntrinsic(engine.world, Matter)
79+
});
80+
81+
const worldCaptureExtrinsic = (world, Matter) => ({
82+
bodies: sortById(Matter.Composite.allBodies(world)).reduce((bodies, body) => {
83+
bodies[body.id] = [
84+
body.position.x,
85+
body.position.y,
86+
body.positionPrev.x,
87+
body.positionPrev.y,
88+
body.angle,
89+
body.anglePrev,
90+
...body.vertices.reduce((flat, vertex) => (flat.push(vertex.x, vertex.y), flat), [])
91+
];
92+
93+
return bodies;
94+
}, {}),
95+
constraints: sortById(Matter.Composite.allConstraints(world)).reduce((constraints, constraint) => {
96+
const positionA = Matter.Constraint.pointAWorld(constraint);
97+
const positionB = Matter.Constraint.pointBWorld(constraint);
98+
99+
constraints[constraint.id] = [
100+
positionA.x,
101+
positionA.y,
102+
positionB.x,
103+
positionB.y
104+
];
105+
106+
return constraints;
107+
}, {})
108+
});
109+
110+
const worldCaptureIntrinsic = (world, Matter) => worldCaptureIntrinsicBase({
111+
bodies: sortById(Matter.Composite.allBodies(world)).reduce((bodies, body) => {
112+
bodies[body.id] = body;
113+
return bodies;
114+
}, {}),
115+
constraints: sortById(Matter.Composite.allConstraints(world)).reduce((constraints, constraint) => {
116+
constraints[constraint.id] = constraint;
117+
return constraints;
118+
}, {}),
119+
composites: sortById(Matter.Composite.allComposites(world)).reduce((composites, composite) => {
120+
composites[composite.id] = {
121+
bodies: sortById(Matter.Composite.allBodies(composite)).map(body => body.id),
122+
constraints: sortById(Matter.Composite.allConstraints(composite)).map(constraint => constraint.id),
123+
composites: sortById(Matter.Composite.allComposites(composite)).map(composite => composite.id)
124+
};
125+
return composites;
126+
}, {})
127+
});
128+
129+
const worldCaptureIntrinsicBase = (obj, depth=0) => {
130+
if (obj === Infinity) {
131+
return 'Infinity';
132+
} else if (typeof obj === 'number') {
133+
return limitPrecision(obj);
134+
} else if (Array.isArray(obj)) {
135+
return obj.map(item => worldCaptureIntrinsicBase(item, depth + 1));
136+
} else if (typeof obj !== 'object') {
137+
return obj;
138+
}
139+
140+
const result = Object.entries(obj)
141+
.filter(([key]) => depth <= 1 || intrinsicProps.includes(key))
142+
.reduce((cleaned, [key, val]) => {
143+
if (val && val.id && String(val.id) !== key) {
144+
val = val.id;
145+
}
146+
147+
if (Array.isArray(val) && !['composites', 'constraints', 'bodies'].includes(key)) {
148+
val = `[${val.length}]`;
149+
}
150+
151+
cleaned[key] = worldCaptureIntrinsicBase(val, depth + 1);
152+
return cleaned;
153+
}, {});
154+
155+
return Object.keys(result).sort()
156+
.reduce((sorted, key) => (sorted[key] = result[key], sorted), {});
157+
};
158+
51159
const runExample = options => {
52160
const Matter = prepareMatter(options);
53161
const logs = prepareEnvironment(Matter);
@@ -107,7 +215,7 @@ const runExample = options => {
107215
overlap: overlapTotal / (overlapCount || 1),
108216
memory: totalMemory,
109217
logs,
110-
...engineCapture(engine)
218+
...engineCapture(engine, Matter)
111219
};
112220
};
113221

test/TestTools.js

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,15 @@
33

44
const fs = require('fs');
55
const compactStringify = require('json-stringify-pretty-compact');
6-
const { Composite, Constraint } = require('../src/module/main');
76

87
const comparePath = './test/__compare__';
98
const compareCommand = 'open http://localhost:8000/?compare';
109
const diffSaveCommand = 'npm run test-save';
1110
const diffCommand = 'code -n -d test/__compare__/examples-build.json test/__compare__/examples-dev.json';
1211
const equalityThreshold = 0.99999;
1312

14-
const intrinsicProps = [
15-
// Common
16-
'id', 'label',
17-
18-
// Constraint
19-
'angularStiffness', 'bodyA', 'bodyB', 'damping', 'length', 'stiffness',
20-
21-
// Body
22-
'area', 'axes', 'collisionFilter', 'category', 'mask',
23-
'group', 'density', 'friction', 'frictionAir', 'frictionStatic', 'inertia', 'inverseInertia', 'inverseMass', 'isSensor',
24-
'isSleeping', 'isStatic', 'mass', 'parent', 'parts', 'restitution', 'sleepThreshold', 'slop',
25-
'timeScale', 'vertices',
26-
27-
// Composite
28-
'bodies', 'constraints', 'composites'
29-
];
30-
3113
const colors = { Red: 31, Green: 32, Yellow: 33, White: 37, BrightWhite: 90, BrightCyan: 36 };
3214
const color = (text, number) => number ? `\x1b[${number}m${text}\x1b[0m` : text;
33-
const limit = (val, precision=3) => parseFloat(val.toPrecision(precision));
3415
const toPercent = val => (100 * val).toFixed(3);
3516
const toPercentRound = val => Math.round(100 * val);
3617

@@ -47,90 +28,6 @@ const noiseThreshold = (val, threshold) => {
4728
return sign * Math.max(0, magnitude - threshold) / (1 - threshold);
4829
};
4930

50-
const engineCapture = (engine) => ({
51-
timestamp: limit(engine.timing.timestamp),
52-
extrinsic: worldCaptureExtrinsic(engine.world),
53-
intrinsic: worldCaptureIntrinsic(engine.world)
54-
});
55-
56-
const worldCaptureExtrinsic = world => ({
57-
bodies: Composite.allBodies(world).reduce((bodies, body) => {
58-
bodies[body.id] = [
59-
body.position.x,
60-
body.position.y,
61-
body.positionPrev.x,
62-
body.positionPrev.y,
63-
body.angle,
64-
body.anglePrev,
65-
...body.vertices.reduce((flat, vertex) => (flat.push(vertex.x, vertex.y), flat), [])
66-
];
67-
68-
return bodies;
69-
}, {}),
70-
constraints: Composite.allConstraints(world).reduce((constraints, constraint) => {
71-
const positionA = Constraint.pointAWorld(constraint);
72-
const positionB = Constraint.pointBWorld(constraint);
73-
74-
constraints[constraint.id] = [
75-
positionA.x,
76-
positionA.y,
77-
positionB.x,
78-
positionB.y
79-
];
80-
81-
return constraints;
82-
}, {})
83-
});
84-
85-
const worldCaptureIntrinsic = world => worldCaptureIntrinsicBase({
86-
bodies: Composite.allBodies(world).reduce((bodies, body) => {
87-
bodies[body.id] = body;
88-
return bodies;
89-
}, {}),
90-
constraints: Composite.allConstraints(world).reduce((constraints, constraint) => {
91-
constraints[constraint.id] = constraint;
92-
return constraints;
93-
}, {}),
94-
composites: Composite.allComposites(world).reduce((composites, composite) => {
95-
composites[composite.id] = {
96-
bodies: Composite.allBodies(composite).map(body => body.id),
97-
constraints: Composite.allConstraints(composite).map(constraint => constraint.id),
98-
composites: Composite.allComposites(composite).map(composite => composite.id)
99-
};
100-
return composites;
101-
}, {})
102-
});
103-
104-
const worldCaptureIntrinsicBase = (obj, depth=0) => {
105-
if (obj === Infinity) {
106-
return 'Infinity';
107-
} else if (typeof obj === 'number') {
108-
return limit(obj);
109-
} else if (Array.isArray(obj)) {
110-
return obj.map(item => worldCaptureIntrinsicBase(item, depth + 1));
111-
} else if (typeof obj !== 'object') {
112-
return obj;
113-
}
114-
115-
const result = Object.entries(obj)
116-
.filter(([key]) => depth <= 1 || intrinsicProps.includes(key))
117-
.reduce((cleaned, [key, val]) => {
118-
if (val && val.id && String(val.id) !== key) {
119-
val = val.id;
120-
}
121-
122-
if (Array.isArray(val) && !['composites', 'constraints', 'bodies'].includes(key)) {
123-
val = `[${val.length}]`;
124-
}
125-
126-
cleaned[key] = worldCaptureIntrinsicBase(val, depth + 1);
127-
return cleaned;
128-
}, {});
129-
130-
return Object.keys(result).sort()
131-
.reduce((sorted, key) => (sorted[key] = result[key], sorted), {});
132-
};
133-
13431
const similarity = (a, b) => {
13532
const distance = Math.sqrt(a.reduce(
13633
(sum, _val, i) => sum + Math.pow((a[i] || 0) - (b[i] || 0), 2), 0)
@@ -325,6 +222,6 @@ const comparisonReport = (capturesDev, capturesBuild, devSize, buildSize, buildV
325222
};
326223

327224
module.exports = {
328-
requireUncached, engineCapture, comparisonReport, logReport,
225+
requireUncached, comparisonReport, logReport,
329226
toMatchExtrinsics, toMatchIntrinsics
330227
};

0 commit comments

Comments
 (0)