@jetta/axle-load-calculator 0.3.1 → 0.3.2

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.
@@ -2,6 +2,7 @@ import { CenterOfMass } from '../physics/items/CenterOfMass.js';
2
2
  /**
3
3
  * Computes mass center per grouper using ms-faixas Java Item / MassCenter rules.
4
4
  * Longitudinal position uses JSON `y` (maps to Ponto3D.z in Java CubeRepresentation).
5
+ * Same-grouper containers are merged; empty necks do not shift later beds (MS parity).
5
6
  * @param env_vehicle - Single env vehicle object from weight_by_axis payload.
6
7
  * @returns Map of grouper id to center of mass.
7
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"JavaMassCenter.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/JavaMassCenter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAE/D;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAe9B"}
1
+ {"version":3,"file":"JavaMassCenter.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/JavaMassCenter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAE/D;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAQ9B"}
@@ -2,46 +2,99 @@ import { CenterOfMass } from '../physics/items/CenterOfMass.js';
2
2
  /**
3
3
  * Computes mass center per grouper using ms-faixas Java Item / MassCenter rules.
4
4
  * Longitudinal position uses JSON `y` (maps to Ponto3D.z in Java CubeRepresentation).
5
+ * Same-grouper containers are merged; empty necks do not shift later beds (MS parity).
5
6
  * @param env_vehicle - Single env vehicle object from weight_by_axis payload.
6
7
  * @returns Map of grouper id to center of mass.
7
8
  */
8
9
  export function mass_center_by_grouper_from_env(env_vehicle) {
9
- const result = {};
10
10
  const containers = env_vehicle.containers;
11
11
  if (!containers) {
12
- return result;
12
+ return {};
13
13
  }
14
+ return accumulate_grouper_mass_centers(sort_containers_by_sequence(containers));
15
+ }
16
+ /**
17
+ * @param containers - Containers sorted by sequencia.
18
+ * @returns Merged center of mass map keyed by grouper.
19
+ */
20
+ function accumulate_grouper_mass_centers(containers) {
21
+ const result = {};
22
+ const longitudinal_offset_by_grouper = {};
14
23
  for (const container of containers) {
15
- const grouper = Number(container.grouper);
16
- // Java AxleWeightConnector overwrites per container in loop order (last wins).
17
- result[grouper] = compute_container_mass_center(container);
24
+ absorb_container_into_grouper(result, longitudinal_offset_by_grouper, container);
18
25
  }
19
26
  return result;
20
27
  }
28
+ /**
29
+ * @param result - Accumulated grouper centers (mutated).
30
+ * @param offsets - Longitudinal offset per grouper (mutated).
31
+ * @param container - Env container to absorb.
32
+ */
33
+ function absorb_container_into_grouper(result, offsets, container) {
34
+ const grouper = Number(container.grouper);
35
+ const sequence_offset = offsets[grouper] ?? 0;
36
+ const container_center = compute_container_mass_center(container, sequence_offset);
37
+ result[grouper] = result[grouper]
38
+ ? merge_mass_centers(result[grouper], container_center)
39
+ : container_center;
40
+ if (container_center.mass > 0) {
41
+ offsets[grouper] = sequence_offset + Number(container.comprimento ?? 0);
42
+ }
43
+ }
44
+ /**
45
+ * @param containers - Env containers.
46
+ * @returns Containers sorted by sequencia ascending.
47
+ */
48
+ function sort_containers_by_sequence(containers) {
49
+ return [...containers].sort((left, right) => Number(left.sequencia) - Number(right.sequencia));
50
+ }
51
+ /**
52
+ * @param left - Existing grouper center of mass.
53
+ * @param right - Additional container center of mass.
54
+ * @returns Combined center of mass.
55
+ */
56
+ function merge_mass_centers(left, right) {
57
+ const merged = new CenterOfMass();
58
+ merged.mass = left.mass + right.mass;
59
+ if (merged.mass === 0) {
60
+ merged.z = 0;
61
+ return merged;
62
+ }
63
+ merged.z = (left.mass * left.z + right.mass * right.z) / merged.mass;
64
+ return merged;
65
+ }
21
66
  /**
22
67
  * @param container - Container object with items array.
68
+ * @param sequence_offset - Longitudinal offset from prior same-grouper containers.
23
69
  * @returns Center of mass for container items.
24
70
  */
25
- function compute_container_mass_center(container) {
71
+ function compute_container_mass_center(container, sequence_offset) {
26
72
  const center_of_mass = new CenterOfMass();
27
73
  const items = container.items;
28
74
  if (!items || items.length === 0) {
29
- center_of_mass.mass = 0;
30
- center_of_mass.z = 0;
31
75
  return center_of_mass;
32
76
  }
33
- const container_offset = read_container_longitudinal_offset(container);
77
+ const moments = accumulate_item_moments(items, sequence_offset, container);
78
+ center_of_mass.mass = moments.mass;
79
+ center_of_mass.z = moments.mass === 0 ? 0 : moments.accumulated / moments.mass;
80
+ return center_of_mass;
81
+ }
82
+ /**
83
+ * @param items - Container items.
84
+ * @param sequence_offset - Prior loaded length in grouper.
85
+ * @param container - Container for faixa offset.
86
+ * @returns Accumulated mass and first moment.
87
+ */
88
+ function accumulate_item_moments(items, sequence_offset, container) {
89
+ const container_offset = sequence_offset + read_container_longitudinal_offset(container);
34
90
  let accumulated = 0;
35
91
  let mass = 0;
36
92
  for (const item of items) {
37
93
  const weight = read_item_weight(item);
38
- const position = container_offset + read_item_longitudinal_position(item);
39
- accumulated += weight * position;
94
+ accumulated += weight * (container_offset + read_item_longitudinal_position(item));
40
95
  mass += weight;
41
96
  }
42
- center_of_mass.mass = mass;
43
- center_of_mass.z = mass === 0 ? 0 : accumulated / mass;
44
- return center_of_mass;
97
+ return { accumulated, mass };
45
98
  }
46
99
  /**
47
100
  * @param container - Container JSON.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetta/axle-load-calculator",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Merged weight_by_axis physics and orchestration library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",