@jetta/cargo-stabilizer 0.1.0-10
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/CHANGELOG.md +39 -0
- package/README.md +144 -0
- package/build/core/adapters/axle_adapter.d.ts +16 -0
- package/build/core/adapters/axle_adapter.d.ts.map +1 -0
- package/build/core/adapters/axle_adapter.js +35 -0
- package/build/core/adapters/build_axle_request.d.ts +15 -0
- package/build/core/adapters/build_axle_request.d.ts.map +1 -0
- package/build/core/adapters/build_axle_request.js +39 -0
- package/build/core/adapters/coordinate_mapper.d.ts +36 -0
- package/build/core/adapters/coordinate_mapper.d.ts.map +1 -0
- package/build/core/adapters/coordinate_mapper.js +40 -0
- package/build/core/adapters/empty_space_adapter.d.ts +10 -0
- package/build/core/adapters/empty_space_adapter.d.ts.map +1 -0
- package/build/core/adapters/empty_space_adapter.js +24 -0
- package/build/core/adapters/map_item_to_positioned_cube.d.ts +9 -0
- package/build/core/adapters/map_item_to_positioned_cube.d.ts.map +1 -0
- package/build/core/adapters/map_item_to_positioned_cube.js +16 -0
- package/build/core/adapters/run_axle_calculator.d.ts +16 -0
- package/build/core/adapters/run_axle_calculator.d.ts.map +1 -0
- package/build/core/adapters/run_axle_calculator.js +32 -0
- package/build/core/adapters/stability_adapter.d.ts +36 -0
- package/build/core/adapters/stability_adapter.d.ts.map +1 -0
- package/build/core/adapters/stability_adapter.js +61 -0
- package/build/core/candidates/build_candidate_context.d.ts +13 -0
- package/build/core/candidates/build_candidate_context.d.ts.map +1 -0
- package/build/core/candidates/build_candidate_context.js +17 -0
- package/build/core/candidates/candidate_context.d.ts +13 -0
- package/build/core/candidates/candidate_context.d.ts.map +1 -0
- package/build/core/candidates/candidate_context.js +1 -0
- package/build/core/candidates/candidate_generator.d.ts +9 -0
- package/build/core/candidates/candidate_generator.d.ts.map +1 -0
- package/build/core/candidates/candidate_generator.js +42 -0
- package/build/core/candidates/candidate_validation.d.ts +14 -0
- package/build/core/candidates/candidate_validation.d.ts.map +1 -0
- package/build/core/candidates/candidate_validation.js +72 -0
- package/build/core/candidates/collect_container_slots.d.ts +16 -0
- package/build/core/candidates/collect_container_slots.d.ts.map +1 -0
- package/build/core/candidates/collect_container_slots.js +20 -0
- package/build/core/candidates/enumerate_empty_space_slots.d.ts +15 -0
- package/build/core/candidates/enumerate_empty_space_slots.d.ts.map +1 -0
- package/build/core/candidates/enumerate_empty_space_slots.js +44 -0
- package/build/core/candidates/enumerate_supporter_top_slots.d.ts +11 -0
- package/build/core/candidates/enumerate_supporter_top_slots.d.ts.map +1 -0
- package/build/core/candidates/enumerate_supporter_top_slots.js +36 -0
- package/build/core/candidates/is_elevated_on_supporter_origin.d.ts +14 -0
- package/build/core/candidates/is_elevated_on_supporter_origin.d.ts.map +1 -0
- package/build/core/candidates/is_elevated_on_supporter_origin.js +28 -0
- package/build/core/candidates/rank_candidates.d.ts +9 -0
- package/build/core/candidates/rank_candidates.d.ts.map +1 -0
- package/build/core/candidates/rank_candidates.js +22 -0
- package/build/core/constants/ReorderStrategy.d.ts +11 -0
- package/build/core/constants/ReorderStrategy.d.ts.map +1 -0
- package/build/core/constants/ReorderStrategy.js +9 -0
- package/build/core/constants/TieRatioOrientation.d.ts +6 -0
- package/build/core/constants/TieRatioOrientation.d.ts.map +1 -0
- package/build/core/constants/TieRatioOrientation.js +5 -0
- package/build/core/evaluation/compute_reorder_objective.d.ts +13 -0
- package/build/core/evaluation/compute_reorder_objective.d.ts.map +1 -0
- package/build/core/evaluation/compute_reorder_objective.js +13 -0
- package/build/core/evaluation/evaluation_context.d.ts +14 -0
- package/build/core/evaluation/evaluation_context.d.ts.map +1 -0
- package/build/core/evaluation/evaluation_context.js +1 -0
- package/build/core/evaluation/state_evaluator.d.ts +50 -0
- package/build/core/evaluation/state_evaluator.d.ts.map +1 -0
- package/build/core/evaluation/state_evaluator.js +95 -0
- package/build/core/exceptions/AxleCalculationError.d.ts +4 -0
- package/build/core/exceptions/AxleCalculationError.d.ts.map +1 -0
- package/build/core/exceptions/AxleCalculationError.js +6 -0
- package/build/core/exceptions/InvalidStabilizerInputError.d.ts +4 -0
- package/build/core/exceptions/InvalidStabilizerInputError.d.ts.map +1 -0
- package/build/core/exceptions/InvalidStabilizerInputError.js +6 -0
- package/build/core/exceptions/InvalidStabilizerOutputError.d.ts +4 -0
- package/build/core/exceptions/InvalidStabilizerOutputError.d.ts.map +1 -0
- package/build/core/exceptions/InvalidStabilizerOutputError.js +6 -0
- package/build/core/exceptions/MixedWaypointIdError.d.ts +4 -0
- package/build/core/exceptions/MixedWaypointIdError.d.ts.map +1 -0
- package/build/core/exceptions/MixedWaypointIdError.js +6 -0
- package/build/core/exceptions/UnknownReorderStrategyError.d.ts +4 -0
- package/build/core/exceptions/UnknownReorderStrategyError.d.ts.map +1 -0
- package/build/core/exceptions/UnknownReorderStrategyError.js +6 -0
- package/build/core/factory/read_stabilizer_config.d.ts +10 -0
- package/build/core/factory/read_stabilizer_config.d.ts.map +1 -0
- package/build/core/factory/read_stabilizer_config.js +26 -0
- package/build/core/factory/read_stabilizer_config_helpers.d.ts +29 -0
- package/build/core/factory/read_stabilizer_config_helpers.d.ts.map +1 -0
- package/build/core/factory/read_stabilizer_config_helpers.js +73 -0
- package/build/core/factory/strategy_factory.d.ts +9 -0
- package/build/core/factory/strategy_factory.d.ts.map +1 -0
- package/build/core/factory/strategy_factory.js +29 -0
- package/build/core/filters/collect_movable_items.d.ts +18 -0
- package/build/core/filters/collect_movable_items.d.ts.map +1 -0
- package/build/core/filters/collect_movable_items.js +72 -0
- package/build/core/filters/loose_item_filter.d.ts +20 -0
- package/build/core/filters/loose_item_filter.d.ts.map +1 -0
- package/build/core/filters/loose_item_filter.js +28 -0
- package/build/core/geometry/box_geometry.d.ts +48 -0
- package/build/core/geometry/box_geometry.d.ts.map +1 -0
- package/build/core/geometry/box_geometry.js +98 -0
- package/build/core/logging/stabilizer_logger.d.ts +3 -0
- package/build/core/logging/stabilizer_logger.d.ts.map +1 -0
- package/build/core/logging/stabilizer_logger.js +2 -0
- package/build/core/move/apply_move.d.ts +26 -0
- package/build/core/move/apply_move.d.ts.map +1 -0
- package/build/core/move/apply_move.js +26 -0
- package/build/core/orchestration/StabilizerFlow.d.ts +15 -0
- package/build/core/orchestration/StabilizerFlow.d.ts.map +1 -0
- package/build/core/orchestration/StabilizerFlow.js +29 -0
- package/build/core/orchestration/build_milkrun_bands_from_config.d.ts +13 -0
- package/build/core/orchestration/build_milkrun_bands_from_config.d.ts.map +1 -0
- package/build/core/orchestration/build_milkrun_bands_from_config.js +14 -0
- package/build/core/orchestration/build_reorder_context.d.ts +11 -0
- package/build/core/orchestration/build_reorder_context.d.ts.map +1 -0
- package/build/core/orchestration/build_reorder_context.js +27 -0
- package/build/core/orchestration/read_primary_env.d.ts +9 -0
- package/build/core/orchestration/read_primary_env.d.ts.map +1 -0
- package/build/core/orchestration/read_primary_env.js +13 -0
- package/build/core/strategies/reorder/BeamSearchReorder.d.ts +9 -0
- package/build/core/strategies/reorder/BeamSearchReorder.d.ts.map +1 -0
- package/build/core/strategies/reorder/BeamSearchReorder.js +68 -0
- package/build/core/strategies/reorder/GeneticReorder.d.ts +9 -0
- package/build/core/strategies/reorder/GeneticReorder.d.ts.map +1 -0
- package/build/core/strategies/reorder/GeneticReorder.js +43 -0
- package/build/core/strategies/reorder/GravityCompaction.d.ts +9 -0
- package/build/core/strategies/reorder/GravityCompaction.d.ts.map +1 -0
- package/build/core/strategies/reorder/GravityCompaction.js +48 -0
- package/build/core/strategies/reorder/GreedyReorder.d.ts +9 -0
- package/build/core/strategies/reorder/GreedyReorder.d.ts.map +1 -0
- package/build/core/strategies/reorder/GreedyReorder.js +20 -0
- package/build/core/strategies/reorder/ReorderStrategy.d.ts +19 -0
- package/build/core/strategies/reorder/ReorderStrategy.d.ts.map +1 -0
- package/build/core/strategies/reorder/ReorderStrategy.js +1 -0
- package/build/core/strategies/reorder/SimulatedAnnealingReorder.d.ts +9 -0
- package/build/core/strategies/reorder/SimulatedAnnealingReorder.d.ts.map +1 -0
- package/build/core/strategies/reorder/SimulatedAnnealingReorder.js +61 -0
- package/build/core/strategies/reorder/anneal_helpers.d.ts +18 -0
- package/build/core/strategies/reorder/anneal_helpers.d.ts.map +1 -0
- package/build/core/strategies/reorder/anneal_helpers.js +39 -0
- package/build/core/strategies/reorder/apply_if_gates_pass.d.ts +12 -0
- package/build/core/strategies/reorder/apply_if_gates_pass.d.ts.map +1 -0
- package/build/core/strategies/reorder/apply_if_gates_pass.js +19 -0
- package/build/core/strategies/reorder/beam_context.d.ts +16 -0
- package/build/core/strategies/reorder/beam_context.d.ts.map +1 -0
- package/build/core/strategies/reorder/beam_context.js +1 -0
- package/build/core/strategies/reorder/genetic/Chromosome.d.ts +39 -0
- package/build/core/strategies/reorder/genetic/Chromosome.d.ts.map +1 -0
- package/build/core/strategies/reorder/genetic/Chromosome.js +84 -0
- package/build/core/strategies/reorder/greedy_improvement.d.ts +12 -0
- package/build/core/strategies/reorder/greedy_improvement.d.ts.map +1 -0
- package/build/core/strategies/reorder/greedy_improvement.js +63 -0
- package/build/core/strategies/reorder/select_beam_expansion_candidates.d.ts +9 -0
- package/build/core/strategies/reorder/select_beam_expansion_candidates.d.ts.map +1 -0
- package/build/core/strategies/reorder/select_beam_expansion_candidates.js +28 -0
- package/build/core/validation/contract/cargo_movement_wire_field_map.d.ts +37 -0
- package/build/core/validation/contract/cargo_movement_wire_field_map.d.ts.map +1 -0
- package/build/core/validation/contract/cargo_movement_wire_field_map.js +43 -0
- package/build/core/validation/contract/cargo_movement_wire_mapper.d.ts +14 -0
- package/build/core/validation/contract/cargo_movement_wire_mapper.d.ts.map +1 -0
- package/build/core/validation/contract/cargo_movement_wire_mapper.js +34 -0
- package/build/core/validation/contract/format_zod_error.d.ts +8 -0
- package/build/core/validation/contract/format_zod_error.d.ts.map +1 -0
- package/build/core/validation/contract/format_zod_error.js +11 -0
- package/build/core/validation/contract/index.d.ts +9 -0
- package/build/core/validation/contract/index.d.ts.map +1 -0
- package/build/core/validation/contract/index.js +8 -0
- package/build/core/validation/contract/map_contract_to_wire_shape.d.ts +3 -0
- package/build/core/validation/contract/map_contract_to_wire_shape.d.ts.map +1 -0
- package/build/core/validation/contract/map_contract_to_wire_shape.js +42 -0
- package/build/core/validation/contract/map_wire_input_to_contract_shape.d.ts +2 -0
- package/build/core/validation/contract/map_wire_input_to_contract_shape.d.ts.map +1 -0
- package/build/core/validation/contract/map_wire_input_to_contract_shape.js +60 -0
- package/build/core/validation/contract/map_wire_item_to_contract.d.ts +12 -0
- package/build/core/validation/contract/map_wire_item_to_contract.d.ts.map +1 -0
- package/build/core/validation/contract/map_wire_item_to_contract.js +49 -0
- package/build/core/validation/contract/parse_stabilizer_input.d.ts +48 -0
- package/build/core/validation/contract/parse_stabilizer_input.d.ts.map +1 -0
- package/build/core/validation/contract/parse_stabilizer_input.js +26 -0
- package/build/core/validation/contract/parse_stabilizer_output.d.ts +50 -0
- package/build/core/validation/contract/parse_stabilizer_output.d.ts.map +1 -0
- package/build/core/validation/contract/parse_stabilizer_output.js +24 -0
- package/build/core/validation/contract/stabilizer_domain_schema.d.ts +101 -0
- package/build/core/validation/contract/stabilizer_domain_schema.d.ts.map +1 -0
- package/build/core/validation/contract/stabilizer_domain_schema.js +64 -0
- package/build/core/validation/contract/stabilizer_input_schema.d.ts +36 -0
- package/build/core/validation/contract/stabilizer_input_schema.d.ts.map +1 -0
- package/build/core/validation/contract/stabilizer_input_schema.js +11 -0
- package/build/core/validation/contract/stabilizer_output_schema.d.ts +76 -0
- package/build/core/validation/contract/stabilizer_output_schema.d.ts.map +1 -0
- package/build/core/validation/contract/stabilizer_output_schema.js +16 -0
- package/build/core/validation/contract/wire_mapper_record_utils.d.ts +34 -0
- package/build/core/validation/contract/wire_mapper_record_utils.d.ts.map +1 -0
- package/build/core/validation/contract/wire_mapper_record_utils.js +66 -0
- package/build/core/validation/schemas/stabilizer_config_schema.d.ts +20 -0
- package/build/core/validation/schemas/stabilizer_config_schema.d.ts.map +1 -0
- package/build/core/validation/schemas/stabilizer_config_schema.js +17 -0
- package/build/core/waypoint/WaypointMode.d.ts +16 -0
- package/build/core/waypoint/WaypointMode.d.ts.map +1 -0
- package/build/core/waypoint/WaypointMode.js +1 -0
- package/build/core/waypoint/build_waypoint_zones.d.ts +21 -0
- package/build/core/waypoint/build_waypoint_zones.d.ts.map +1 -0
- package/build/core/waypoint/build_waypoint_zones.js +48 -0
- package/build/core/waypoint/milkrun_wall_reservation.d.ts +24 -0
- package/build/core/waypoint/milkrun_wall_reservation.d.ts.map +1 -0
- package/build/core/waypoint/milkrun_wall_reservation.js +57 -0
- package/build/core/waypoint/milkrun_wall_reservation_helpers.d.ts +15 -0
- package/build/core/waypoint/milkrun_wall_reservation_helpers.d.ts.map +1 -0
- package/build/core/waypoint/milkrun_wall_reservation_helpers.js +48 -0
- package/build/core/waypoint/milkrun_wall_reservation_types.d.ts +16 -0
- package/build/core/waypoint/milkrun_wall_reservation_types.d.ts.map +1 -0
- package/build/core/waypoint/milkrun_wall_reservation_types.js +1 -0
- package/build/core/waypoint/preserves_waypoint_order.d.ts +24 -0
- package/build/core/waypoint/preserves_waypoint_order.d.ts.map +1 -0
- package/build/core/waypoint/preserves_waypoint_order.js +49 -0
- package/build/core/waypoint/validate_waypoint_ids.d.ts +16 -0
- package/build/core/waypoint/validate_waypoint_ids.d.ts.map +1 -0
- package/build/core/waypoint/validate_waypoint_ids.js +30 -0
- package/build/index.d.ts +27 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +75 -0
- package/package.json +51 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@jetta/cargo-stabilizer` are documented in this file.
|
|
4
|
+
|
|
5
|
+
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Strict English internal I/O contract with bidirectional cargo-movement wire mapper (`map_wire_input_to_contract`, `map_contract_to_wire_output`).
|
|
12
|
+
- Organization gates: waypoint Z zones, macro delivery order (`preserve_tie_block_organization`), and milkrun wall reservation (`enforce_milkrun_wall_reservation`).
|
|
13
|
+
- Empty-space candidate discovery for floor and elevated slots via `@jetta/empty-spaces-manager`.
|
|
14
|
+
- Supporter-top candidate slots aligned to each stacked item footprint, included in beam expansion (`top_k ∪ supporter_top`).
|
|
15
|
+
- Elevated candidates must sit on a supporter `(x, z)` origin so stacked loose items copy the supporter footprint.
|
|
16
|
+
- `cargo_stabilizer.pin_tie_ratio_blocks` (default `false`): when true, 3_2/2_3 groups stay pinned; otherwise every item is movable.
|
|
17
|
+
- Public contract exports: `parse_stabilizer_input`, `parse_stabilizer_output`, `safe_parse_stabilizer_input`, `safe_parse_stabilizer_output`, and related domain types.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- README documents I/O contract mapping, configuration keys, dependencies, and test/coverage commands.
|
|
22
|
+
- Reorder objective is whole-cargo `transport_score`; loose-item score sum is only a tie-break. Axle, waypoint, and milkrun gates are unchanged.
|
|
23
|
+
|
|
24
|
+
### Testing
|
|
25
|
+
|
|
26
|
+
- Expanded Mocha suite to 126 tests mirroring `src/` under `test/src/`.
|
|
27
|
+
- Local coverage gate at 80% on lines, functions, branches, and statements (`npm run coverage`).
|
|
28
|
+
- CI coverage gate at 75% (`npm run coverage:ci`).
|
|
29
|
+
- Mocha setup preloads core modules so c8 attributes coverage consistently across the full suite.
|
|
30
|
+
|
|
31
|
+
## [0.1.0-3] - 2026-08-14
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- Initial library scaffold (JET-2262).
|
|
36
|
+
- Five config-selectable reorder strategies: gravity, greedy, beam search, simulated annealing, genetic.
|
|
37
|
+
- Zod-validated input contract with `waypoint_id` rules and multi-container support.
|
|
38
|
+
- Shared evaluator: cargo-stability transport gate, axle-load-calculator folga gate, waypoint order.
|
|
39
|
+
- Public `stabilize()` API compatible with cargo-movement legacy response shape.
|
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# @jetta/cargo-stabilizer
|
|
2
|
+
|
|
3
|
+
TypeScript library that reorders items to improve **whole-cargo transport stability**. By default every item is movable; set `cargo_stabilizer.pin_tie_ratio_blocks` to pin 3_2/2_3 groups. The reorder objective is `transport_score` (loose-item score sum is a tie-break). Implements five config-selectable strategies with organization gates (waypoint order, milkrun wall reservation) and empty-space candidate discovery (JET-2262).
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Node.js 24+
|
|
8
|
+
- npm
|
|
9
|
+
|
|
10
|
+
## How to install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm ci
|
|
14
|
+
npm run build
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Local monorepo development uses `file:` links to `cargo-stability`, `@jetta/axle-load-calculator`, and `@jetta/empty-spaces-manager`.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { stabilize, REORDER_STRATEGY } from '@jetta/cargo-stabilizer'
|
|
23
|
+
|
|
24
|
+
const response = await stabilize({
|
|
25
|
+
cargo_state: {
|
|
26
|
+
envs: [{
|
|
27
|
+
containers: [{
|
|
28
|
+
largura: 2.4,
|
|
29
|
+
altura: 2.7,
|
|
30
|
+
comprimento: 6.0,
|
|
31
|
+
items: [
|
|
32
|
+
{ _id: 'block-1', groupId: 'wall-a', x: 0, y: 0, z: 0, w: 1, h: 1, d: 1 },
|
|
33
|
+
{ _id: 'loose-1', groupId: null, x: 0, y: 1.5, z: 0, w: 0.5, h: 0.5, d: 0.5 }
|
|
34
|
+
]
|
|
35
|
+
}]
|
|
36
|
+
}]
|
|
37
|
+
},
|
|
38
|
+
config: {
|
|
39
|
+
algoritmo: {
|
|
40
|
+
'cargo_stabilizer.reorder_strategy': REORDER_STRATEGY.GRAVITY
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
if (response.status === 'success') {
|
|
46
|
+
console.log(response.data)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## I/O contract
|
|
51
|
+
|
|
52
|
+
The stabilizer uses a **strict English contract** internally (`src/core/validation/contract/`). Cargo-movement wire payloads keep legacy Portuguese keys; a bidirectional mapper translates at the public boundary.
|
|
53
|
+
|
|
54
|
+
| CM wire | Contract (English) |
|
|
55
|
+
|---------|-------------------|
|
|
56
|
+
| `_id` | `item_id` |
|
|
57
|
+
| `groupId` | `group_id` |
|
|
58
|
+
| `w`, `h`, `d` | `width`, `height`, `depth` |
|
|
59
|
+
| `peso` | `weight` |
|
|
60
|
+
| `sequencia` | `sequence` |
|
|
61
|
+
| `largura`, `altura`, `comprimento` | `width`, `height`, `length` |
|
|
62
|
+
| `eixos` | `axles` |
|
|
63
|
+
|
|
64
|
+
Flow: `map_wire_input_to_contract` → strict Zod parse → stabilizer flow → output validation → `map_contract_to_wire_output`.
|
|
65
|
+
|
|
66
|
+
Exported parsers: `parse_stabilizer_input`, `parse_stabilizer_output`, `safe_parse_*`.
|
|
67
|
+
|
|
68
|
+
## Configuration
|
|
69
|
+
|
|
70
|
+
| Key | Default | Description |
|
|
71
|
+
|-----|---------|-------------|
|
|
72
|
+
| `cargo_stabilizer.reorder_strategy` | `gravity` | `gravity`, `greedy`, `beam_search`, `simulated_annealing`, `genetic` |
|
|
73
|
+
| `cargo_stabilizer.transport_stability_floor` | `0` | Hard minimum transport stability score (gate, not the maximize objective) |
|
|
74
|
+
| `cargo_stabilizer.max_iteration` | `10` | Greedy / SA iteration budget |
|
|
75
|
+
| `cargo_stabilizer.preserve_tie_block_organization` | `true` | When true, enforce waypoint Z zones and macro delivery order |
|
|
76
|
+
| `cargo_stabilizer.pin_tie_ratio_blocks` | `false` | When true, do not move 3_2/2_3 groups; other items remain movable |
|
|
77
|
+
| `cargo_stabilizer.enforce_milkrun_wall_reservation` | `false` | When true, reserve rear compound-wall Z bands using profile key below |
|
|
78
|
+
| `number_of_wall_to_allocate_from_last_waypoints` | `0` | Count of trailing waypoints whose compound walls are reserved (read from `cargo_state.config.algoritmo` when milkrun enforcement is enabled) |
|
|
79
|
+
| `folga_de_peso_nos_eixos` | `0` | Axle folga percent |
|
|
80
|
+
|
|
81
|
+
## Errors
|
|
82
|
+
|
|
83
|
+
| Error | When |
|
|
84
|
+
|-------|------|
|
|
85
|
+
| `InvalidStabilizerInputError` | Zod validation failure on input |
|
|
86
|
+
| `InvalidStabilizerOutputError` | Internal response failed output contract parse |
|
|
87
|
+
| `MixedWaypointIdError` | Some items have `waypoint_id` and others omit it |
|
|
88
|
+
| `UnknownReorderStrategyError` | Invalid `cargo_stabilizer.reorder_strategy` |
|
|
89
|
+
|
|
90
|
+
Import `ZodError` from `zod` when validating externally.
|
|
91
|
+
|
|
92
|
+
## Dependencies
|
|
93
|
+
|
|
94
|
+
Runtime integrations (all declared in `package.json`):
|
|
95
|
+
|
|
96
|
+
- `@jetta/cargo-stability` — transport stability scoring gate and objective (`stability_adapter`)
|
|
97
|
+
- `@jetta/axle-load-calculator` — axle load validation gate (`axle_adapter`)
|
|
98
|
+
- `@jetta/empty-spaces-manager` — empty-region candidate slot discovery (`empty_space_adapter`)
|
|
99
|
+
- `@jetta/logger` — structured logging at orchestration boundary (transitive via cargo-stability)
|
|
100
|
+
- `zod` — I/O contract validation
|
|
101
|
+
|
|
102
|
+
## Scripts
|
|
103
|
+
|
|
104
|
+
| Command | Description |
|
|
105
|
+
|---------|-------------|
|
|
106
|
+
| `npm test` | Mocha tests (126 cases) |
|
|
107
|
+
| `npm run lint` | ESLint |
|
|
108
|
+
| `npm run build` | TypeScript compile to `build/` |
|
|
109
|
+
| `npm run coverage` | Tests with **80%** coverage gate (local) |
|
|
110
|
+
| `npm run coverage:ci` | Tests with **75%** coverage gate (CI) |
|
|
111
|
+
| `npm run lint:package` | publint strict check |
|
|
112
|
+
|
|
113
|
+
## Layout
|
|
114
|
+
|
|
115
|
+
- `src/index.ts` — public API (`stabilize`)
|
|
116
|
+
- `src/core/validation/contract/` — strict English I/O contract and CM wire mapper
|
|
117
|
+
- `src/core/strategies/reorder/` — five reorder algorithms
|
|
118
|
+
- `src/core/evaluation/` — shared stability + axle + waypoint gates
|
|
119
|
+
- `src/core/candidates/` — empty-space slot discovery and candidate ranking
|
|
120
|
+
- `test/src/` — mirrors `src/`; fixtures under `test/data/src/`
|
|
121
|
+
|
|
122
|
+
## Testing and coverage
|
|
123
|
+
|
|
124
|
+
Tests run via Mocha + Chai with quiet logging (`test/mocha_setup.ts`). Core modules are preloaded at startup so `c8` reports accurate coverage when the full suite runs.
|
|
125
|
+
|
|
126
|
+
| Gate | Command | Threshold |
|
|
127
|
+
|------|---------|-----------|
|
|
128
|
+
| Local | `npm run coverage` | 80% lines, functions, branches, statements |
|
|
129
|
+
| CI | `npm run coverage:ci` | 75% on all metrics |
|
|
130
|
+
|
|
131
|
+
## Test plan
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npm test -- --grep "wire_mapper_shape"
|
|
135
|
+
npm test -- --grep "input_validation"
|
|
136
|
+
npm test -- --grep "waypoint_order"
|
|
137
|
+
npm test -- --grep "milkrun_wall_reservation"
|
|
138
|
+
npm test -- --grep "apply_move"
|
|
139
|
+
npm test -- --grep "state_evaluator"
|
|
140
|
+
npm test -- --grep "gravity_compaction"
|
|
141
|
+
npm test -- --grep "reorder_strategy_depth"
|
|
142
|
+
npm test -- --grep "strategy_factory"
|
|
143
|
+
npm run coverage
|
|
144
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StabilizerEnv } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* @param final_kg - Loaded weight including tare.
|
|
4
|
+
* @param max_kg - Axle supported max.
|
|
5
|
+
* @param folga_pct - Axle load margin percent from profile.
|
|
6
|
+
* @returns True when axle exceeds under folga rule.
|
|
7
|
+
*/
|
|
8
|
+
export declare function exceeds_with_folga(final_kg: number, max_kg: number, folga_pct: number): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Validates axle loads for an env using axle-load-calculator.
|
|
11
|
+
* @param env - Stabilizer env with containers and axles.
|
|
12
|
+
* @param folga_pct - Axle load margin percent.
|
|
13
|
+
* @returns True when all axles are within limits.
|
|
14
|
+
*/
|
|
15
|
+
export declare function is_axle_load_valid(env: StabilizerEnv, folga_pct: number): boolean;
|
|
16
|
+
//# sourceMappingURL=axle_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axle_adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/axle_adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oDAAoD,CAAA;AAEvF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAClB,OAAO,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAejF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { run_axle_calculator } from './run_axle_calculator.js';
|
|
2
|
+
/**
|
|
3
|
+
* @param final_kg - Loaded weight including tare.
|
|
4
|
+
* @param max_kg - Axle supported max.
|
|
5
|
+
* @param folga_pct - Axle load margin percent from profile.
|
|
6
|
+
* @returns True when axle exceeds under folga rule.
|
|
7
|
+
*/
|
|
8
|
+
export function exceeds_with_folga(final_kg, max_kg, folga_pct) {
|
|
9
|
+
return final_kg > max_kg * (1 + folga_pct / 100);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validates axle loads for an env using axle-load-calculator.
|
|
13
|
+
* @param env - Stabilizer env with containers and axles.
|
|
14
|
+
* @param folga_pct - Axle load margin percent.
|
|
15
|
+
* @returns True when all axles are within limits.
|
|
16
|
+
*/
|
|
17
|
+
export function is_axle_load_valid(env, folga_pct) {
|
|
18
|
+
if (!env.axles || env.axles.length === 0) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const result = run_axle_calculator(env);
|
|
22
|
+
if (!result.calculated) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const containers = (result.env.containers ?? []);
|
|
26
|
+
return containers.every(container => container_axles_within_folga(container, folga_pct));
|
|
27
|
+
}
|
|
28
|
+
function container_axles_within_folga(container, folga_pct) {
|
|
29
|
+
const axles = (container.pesoEixos ?? []);
|
|
30
|
+
return axles.every(axle => {
|
|
31
|
+
const final_kg = Number(axle.pesoCarregadoFinal ?? 0);
|
|
32
|
+
const max_kg = Number(axle.pesoMaxFinal ?? 0);
|
|
33
|
+
return !exceeds_with_folga(final_kg, max_kg, folga_pct);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { StabilizerEnv } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the axle-load-calculator request for a single env.
|
|
4
|
+
*
|
|
5
|
+
* The calculator physics reads `peso`, `largura`, `altura` and `comprimento`
|
|
6
|
+
* (ItemTemplates and JavaMassCenter), none of which exist in the
|
|
7
|
+
* cargo-movement wire item shape (`wg`, `w`, `h`, `d`). Without these aliases
|
|
8
|
+
* every item weighs zero and the axle gate can never reject a layout, so the
|
|
9
|
+
* contract values are stamped onto each request item here. Longitudinal extent
|
|
10
|
+
* is `depth`, matching the wire `y` axis the calculator uses for equilibrium.
|
|
11
|
+
* @param env - Stabilizer env with containers and axles.
|
|
12
|
+
* @returns Calculator request payload.
|
|
13
|
+
*/
|
|
14
|
+
export declare function build_axle_request(env: StabilizerEnv): Record<string, unknown>;
|
|
15
|
+
//# sourceMappingURL=build_axle_request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build_axle_request.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/build_axle_request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAER,aAAa,EAEhB,MAAM,oDAAoD,CAAA;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAS9E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { map_contract_to_wire_output } from '../validation/contract/cargo_movement_wire_mapper.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the axle-load-calculator request for a single env.
|
|
4
|
+
*
|
|
5
|
+
* The calculator physics reads `peso`, `largura`, `altura` and `comprimento`
|
|
6
|
+
* (ItemTemplates and JavaMassCenter), none of which exist in the
|
|
7
|
+
* cargo-movement wire item shape (`wg`, `w`, `h`, `d`). Without these aliases
|
|
8
|
+
* every item weighs zero and the axle gate can never reject a layout, so the
|
|
9
|
+
* contract values are stamped onto each request item here. Longitudinal extent
|
|
10
|
+
* is `depth`, matching the wire `y` axis the calculator uses for equilibrium.
|
|
11
|
+
* @param env - Stabilizer env with containers and axles.
|
|
12
|
+
* @returns Calculator request payload.
|
|
13
|
+
*/
|
|
14
|
+
export function build_axle_request(env) {
|
|
15
|
+
const wire = map_contract_to_wire_output({ envs: [env] });
|
|
16
|
+
const wire_env = wire.envs[0];
|
|
17
|
+
const wire_containers = (wire_env.containers ?? []);
|
|
18
|
+
wire_env.containers = wire_containers.map((wire_container, index) => stamp_container_physics_aliases(wire_container, env.containers[index]));
|
|
19
|
+
return { envs: wire.envs };
|
|
20
|
+
}
|
|
21
|
+
function stamp_container_physics_aliases(wire_container, container) {
|
|
22
|
+
const wire_items = (wire_container.items ?? []);
|
|
23
|
+
return {
|
|
24
|
+
...wire_container,
|
|
25
|
+
items: wire_items.map((wire_item, index) => stamp_item_physics_aliases(wire_item, container?.items[index]))
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function stamp_item_physics_aliases(wire_item, item) {
|
|
29
|
+
if (item === undefined) {
|
|
30
|
+
return wire_item;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
...wire_item,
|
|
34
|
+
peso: item.weight ?? 0,
|
|
35
|
+
largura: item.width,
|
|
36
|
+
altura: item.height,
|
|
37
|
+
comprimento: item.depth
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StabilizerContainer, StabilizerItem } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
import { type AxisAlignedBox } from '../geometry/box_geometry.js';
|
|
3
|
+
export interface StabilityItemPayload {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
z: number;
|
|
7
|
+
w: number;
|
|
8
|
+
h: number;
|
|
9
|
+
l: number;
|
|
10
|
+
}
|
|
11
|
+
export interface StabilityContainerPayload {
|
|
12
|
+
w: number;
|
|
13
|
+
h: number;
|
|
14
|
+
l: number;
|
|
15
|
+
item_list: StabilityItemPayload[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Maps contract coordinates to cargo-stability payload coordinates.
|
|
19
|
+
* @param item - Stabilizer item record.
|
|
20
|
+
* @returns Stability item payload entry.
|
|
21
|
+
*/
|
|
22
|
+
export declare function map_item_to_stability(item: StabilizerItem): StabilityItemPayload;
|
|
23
|
+
/**
|
|
24
|
+
* Builds cargo-stability transport input from stabilizer containers.
|
|
25
|
+
* @param containers - Stabilizer container records.
|
|
26
|
+
* @returns Stability containers array.
|
|
27
|
+
*/
|
|
28
|
+
export declare function build_stability_containers(containers: StabilizerContainer[]): StabilityContainerPayload[];
|
|
29
|
+
/**
|
|
30
|
+
* Collects all item boxes in a container, optionally excluding one item id.
|
|
31
|
+
* @param container - Container with items.
|
|
32
|
+
* @param exclude_item_id - Item id to skip (virtual remove).
|
|
33
|
+
* @returns Bounding boxes for remaining items.
|
|
34
|
+
*/
|
|
35
|
+
export declare function collect_container_boxes(container: StabilizerContainer, exclude_item_id?: string): AxisAlignedBox[];
|
|
36
|
+
//# sourceMappingURL=coordinate_mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate_mapper.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/coordinate_mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AAC7G,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAE9E,MAAM,WAAW,oBAAoB;IAEjC,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,yBAAyB;IAEtC,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,SAAS,EAAE,oBAAoB,EAAE,CAAA;CACpC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,cAAc,GAAG,oBAAoB,CAUhF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACtC,UAAU,EAAE,mBAAmB,EAAE,GAClC,yBAAyB,EAAE,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACnC,SAAS,EAAE,mBAAmB,EAC9B,eAAe,CAAC,EAAE,MAAM,GACzB,cAAc,EAAE,CAKlB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { item_to_box } from '../geometry/box_geometry.js';
|
|
2
|
+
/**
|
|
3
|
+
* Maps contract coordinates to cargo-stability payload coordinates.
|
|
4
|
+
* @param item - Stabilizer item record.
|
|
5
|
+
* @returns Stability item payload entry.
|
|
6
|
+
*/
|
|
7
|
+
export function map_item_to_stability(item) {
|
|
8
|
+
return {
|
|
9
|
+
x: item.x,
|
|
10
|
+
y: item.z,
|
|
11
|
+
z: item.y,
|
|
12
|
+
w: item.width,
|
|
13
|
+
h: item.height,
|
|
14
|
+
l: item.depth
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds cargo-stability transport input from stabilizer containers.
|
|
19
|
+
* @param containers - Stabilizer container records.
|
|
20
|
+
* @returns Stability containers array.
|
|
21
|
+
*/
|
|
22
|
+
export function build_stability_containers(containers) {
|
|
23
|
+
return containers.map(container => ({
|
|
24
|
+
w: container.width,
|
|
25
|
+
h: container.height,
|
|
26
|
+
l: container.length,
|
|
27
|
+
item_list: container.items.map(map_item_to_stability)
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Collects all item boxes in a container, optionally excluding one item id.
|
|
32
|
+
* @param container - Container with items.
|
|
33
|
+
* @param exclude_item_id - Item id to skip (virtual remove).
|
|
34
|
+
* @returns Bounding boxes for remaining items.
|
|
35
|
+
*/
|
|
36
|
+
export function collect_container_boxes(container, exclude_item_id) {
|
|
37
|
+
return container.items
|
|
38
|
+
.filter(item => item.item_id !== exclude_item_id)
|
|
39
|
+
.map(item_to_box);
|
|
40
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Space } from '@jetta/empty-spaces-manager';
|
|
2
|
+
import type { StabilizerContainer } from '../validation/contract/stabilizer_domain_schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Finds empty regions in a container after allocating pinned and other items.
|
|
5
|
+
* @param container - Stabilizer container layout.
|
|
6
|
+
* @param exclude_item_id - Loose item id to omit from obstacles (virtual remove).
|
|
7
|
+
* @returns Empty space fragments from EmptySpaceFinder.
|
|
8
|
+
*/
|
|
9
|
+
export declare function find_empty_spaces_in_container(container: StabilizerContainer, exclude_item_id?: string): Space[];
|
|
10
|
+
//# sourceMappingURL=empty_space_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty_space_adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/empty_space_adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAErE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAA;AAE7F;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC1C,SAAS,EAAE,mBAAmB,EAC9B,eAAe,CAAC,EAAE,MAAM,GACzB,KAAK,EAAE,CAgBT"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EmptySpaceFinder, Space } from '@jetta/empty-spaces-manager';
|
|
2
|
+
import { map_item_to_positioned_cube } from './map_item_to_positioned_cube.js';
|
|
3
|
+
/**
|
|
4
|
+
* Finds empty regions in a container after allocating pinned and other items.
|
|
5
|
+
* @param container - Stabilizer container layout.
|
|
6
|
+
* @param exclude_item_id - Loose item id to omit from obstacles (virtual remove).
|
|
7
|
+
* @returns Empty space fragments from EmptySpaceFinder.
|
|
8
|
+
*/
|
|
9
|
+
export function find_empty_spaces_in_container(container, exclude_item_id) {
|
|
10
|
+
const container_space = new Space({
|
|
11
|
+
x: 0,
|
|
12
|
+
y: 0,
|
|
13
|
+
z: 0,
|
|
14
|
+
width: container.width,
|
|
15
|
+
height: container.height,
|
|
16
|
+
length: container.length
|
|
17
|
+
});
|
|
18
|
+
const obstacles = container.items
|
|
19
|
+
.filter(item => item.item_id !== exclude_item_id)
|
|
20
|
+
.map(map_item_to_positioned_cube);
|
|
21
|
+
const finder = new EmptySpaceFinder(container_space, []);
|
|
22
|
+
finder.allocate_item_list(obstacles);
|
|
23
|
+
return finder.empty_spaces();
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Space } from '@jetta/empty-spaces-manager';
|
|
2
|
+
import type { StabilizerItem } from '../validation/contract/stabilizer_domain_schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Maps a stabilizer item to an empty-spaces positioned cube.
|
|
5
|
+
* @param item - Stabilizer item record.
|
|
6
|
+
* @returns Positioned cube for EmptySpaceFinder allocation.
|
|
7
|
+
*/
|
|
8
|
+
export declare function map_item_to_positioned_cube(item: StabilizerItem): Space;
|
|
9
|
+
//# sourceMappingURL=map_item_to_positioned_cube.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map_item_to_positioned_cube.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/map_item_to_positioned_cube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAA;AAExF;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,cAAc,GAAG,KAAK,CAUvE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Space } from '@jetta/empty-spaces-manager';
|
|
2
|
+
/**
|
|
3
|
+
* Maps a stabilizer item to an empty-spaces positioned cube.
|
|
4
|
+
* @param item - Stabilizer item record.
|
|
5
|
+
* @returns Positioned cube for EmptySpaceFinder allocation.
|
|
6
|
+
*/
|
|
7
|
+
export function map_item_to_positioned_cube(item) {
|
|
8
|
+
return new Space({
|
|
9
|
+
x: item.x,
|
|
10
|
+
y: item.y,
|
|
11
|
+
z: item.z,
|
|
12
|
+
width: item.width,
|
|
13
|
+
height: item.height,
|
|
14
|
+
length: item.depth
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StabilizerEnv } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
export type AxleCalculatorResult = {
|
|
3
|
+
calculated: true;
|
|
4
|
+
env: Record<string, unknown>;
|
|
5
|
+
} | {
|
|
6
|
+
calculated: false;
|
|
7
|
+
reason: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Runs the axle-load calculator for a candidate env layout.
|
|
11
|
+
* @param env - Stabilizer env with containers and axles.
|
|
12
|
+
* @returns Calculated env, or the reason the layout was rejected.
|
|
13
|
+
* @throws {AxleCalculationError} When the vehicle or item configuration cannot be calculated.
|
|
14
|
+
*/
|
|
15
|
+
export declare function run_axle_calculator(env: StabilizerEnv): AxleCalculatorResult;
|
|
16
|
+
//# sourceMappingURL=run_axle_calculator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run_axle_calculator.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/run_axle_calculator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oDAAoD,CAAA;AASvF,MAAM,MAAM,oBAAoB,GAC1B;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAClD;IAAE,UAAU,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,oBAAoB,CAoB5E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { calculate_weight_on_axles_physics } from '@jetta/axle-load-calculator';
|
|
2
|
+
import { build_axle_request } from './build_axle_request.js';
|
|
3
|
+
import { AxleCalculationError } from '../exceptions/AxleCalculationError.js';
|
|
4
|
+
import { stabilizer_logger } from '../logging/stabilizer_logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Calculator failures caused by the candidate layout rather than by the vehicle
|
|
7
|
+
* or item configuration. These reject the candidate layout; every other failure
|
|
8
|
+
* means the env can never be evaluated and aborts the run.
|
|
9
|
+
*/
|
|
10
|
+
const LAYOUT_REJECTION_MESSAGES = Object.freeze(['Item overlap error']);
|
|
11
|
+
/**
|
|
12
|
+
* Runs the axle-load calculator for a candidate env layout.
|
|
13
|
+
* @param env - Stabilizer env with containers and axles.
|
|
14
|
+
* @returns Calculated env, or the reason the layout was rejected.
|
|
15
|
+
* @throws {AxleCalculationError} When the vehicle or item configuration cannot be calculated.
|
|
16
|
+
*/
|
|
17
|
+
export function run_axle_calculator(env) {
|
|
18
|
+
const request = build_axle_request(env);
|
|
19
|
+
const output = JSON.parse(calculate_weight_on_axles_physics(JSON.stringify(request)));
|
|
20
|
+
if (Array.isArray(output.envs) && output.envs.length > 0) {
|
|
21
|
+
return { calculated: true, env: output.envs[0] };
|
|
22
|
+
}
|
|
23
|
+
const reason = output.apiError ?? 'calculator returned no envs';
|
|
24
|
+
if (!is_layout_rejection(reason)) {
|
|
25
|
+
throw new AxleCalculationError(reason);
|
|
26
|
+
}
|
|
27
|
+
stabilizer_logger.debug('axle gate rejected candidate layout: ' + reason);
|
|
28
|
+
return { calculated: false, reason };
|
|
29
|
+
}
|
|
30
|
+
function is_layout_rejection(reason) {
|
|
31
|
+
return LAYOUT_REJECTION_MESSAGES.some(message => reason.includes(message));
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StabilizerContainer } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
import type { LooseItemRef } from '../filters/loose_item_filter.js';
|
|
3
|
+
export interface StabilityEvaluation {
|
|
4
|
+
item_scores: number[][];
|
|
5
|
+
container_scores: number[];
|
|
6
|
+
transport_score: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Evaluates transport stability for CM containers.
|
|
10
|
+
* @param containers - CM container list.
|
|
11
|
+
* @returns Per-item and transport stability scores.
|
|
12
|
+
*/
|
|
13
|
+
export declare function evaluate_transport_stability(containers: StabilizerContainer[]): StabilityEvaluation;
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates transport stability, returning undefined when cargo-stability rejects layout.
|
|
16
|
+
* @param containers - CM container list.
|
|
17
|
+
* @returns Stability scores or undefined on invalid geometry/score.
|
|
18
|
+
*/
|
|
19
|
+
export declare function try_evaluate_transport_stability(containers: StabilizerContainer[]): StabilityEvaluation | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Sums stability scores for loose items only.
|
|
22
|
+
* @param stability - Stability evaluation result.
|
|
23
|
+
* @param containers - CM containers (for index lookup).
|
|
24
|
+
* @param loose_items - Loose item references.
|
|
25
|
+
* @returns Sum of loose item scores.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sum_loose_item_scores(stability: StabilityEvaluation, containers: StabilizerContainer[], loose_items: LooseItemRef[]): number;
|
|
28
|
+
/**
|
|
29
|
+
* Reads a single item stability score.
|
|
30
|
+
* @param stability - Stability evaluation.
|
|
31
|
+
* @param container_index - Container index.
|
|
32
|
+
* @param item_index - Item index in container.
|
|
33
|
+
* @returns Item score or zero when missing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function read_item_score(stability: StabilityEvaluation, container_index: number, item_index: number): number;
|
|
36
|
+
//# sourceMappingURL=stability_adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stability_adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/stability_adapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAA;AAC7F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAEnE,MAAM,WAAW,mBAAmB;IAEhC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAA;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,UAAU,EAAE,mBAAmB,EAAE,GAClC,mBAAmB,CAiBrB;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC5C,UAAU,EAAE,mBAAmB,EAAE,GAClC,mBAAmB,GAAG,SAAS,CAUjC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,mBAAmB,EAC9B,UAAU,EAAE,mBAAmB,EAAE,EACjC,WAAW,EAAE,YAAY,EAAE,GAC5B,MAAM,CAgBR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,mBAAmB,EAC9B,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,GACnB,MAAM,CAGR"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { calculate_cargo_stability } from '@jetta/cargo-stability';
|
|
2
|
+
import { build_stability_containers } from './coordinate_mapper.js';
|
|
3
|
+
/**
|
|
4
|
+
* Evaluates transport stability for CM containers.
|
|
5
|
+
* @param containers - CM container list.
|
|
6
|
+
* @returns Per-item and transport stability scores.
|
|
7
|
+
*/
|
|
8
|
+
export function evaluate_transport_stability(containers) {
|
|
9
|
+
const payload = {
|
|
10
|
+
calculation_type: 'transport',
|
|
11
|
+
containers: build_stability_containers(containers)
|
|
12
|
+
};
|
|
13
|
+
const result = calculate_cargo_stability(payload);
|
|
14
|
+
return {
|
|
15
|
+
item_scores: result.items,
|
|
16
|
+
container_scores: result.containers,
|
|
17
|
+
transport_score: result.transport
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates transport stability, returning undefined when cargo-stability rejects layout.
|
|
22
|
+
* @param containers - CM container list.
|
|
23
|
+
* @returns Stability scores or undefined on invalid geometry/score.
|
|
24
|
+
*/
|
|
25
|
+
export function try_evaluate_transport_stability(containers) {
|
|
26
|
+
try {
|
|
27
|
+
return evaluate_transport_stability(containers);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Sums stability scores for loose items only.
|
|
35
|
+
* @param stability - Stability evaluation result.
|
|
36
|
+
* @param containers - CM containers (for index lookup).
|
|
37
|
+
* @param loose_items - Loose item references.
|
|
38
|
+
* @returns Sum of loose item scores.
|
|
39
|
+
*/
|
|
40
|
+
export function sum_loose_item_scores(stability, containers, loose_items) {
|
|
41
|
+
let total = 0;
|
|
42
|
+
for (const loose of loose_items) {
|
|
43
|
+
const container = containers[loose.container_index];
|
|
44
|
+
const item_index = container.items.findIndex(item => item.item_id === loose.item_id);
|
|
45
|
+
if (item_index < 0) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
total += stability.item_scores[loose.container_index]?.[item_index] ?? 0;
|
|
49
|
+
}
|
|
50
|
+
return total;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reads a single item stability score.
|
|
54
|
+
* @param stability - Stability evaluation.
|
|
55
|
+
* @param container_index - Container index.
|
|
56
|
+
* @param item_index - Item index in container.
|
|
57
|
+
* @returns Item score or zero when missing.
|
|
58
|
+
*/
|
|
59
|
+
export function read_item_score(stability, container_index, item_index) {
|
|
60
|
+
return stability.item_scores[container_index]?.[item_index] ?? 0;
|
|
61
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { StabilizerContainer } from '../validation/contract/stabilizer_domain_schema.js';
|
|
2
|
+
import type { LooseItemRef } from '../filters/loose_item_filter.js';
|
|
3
|
+
import type { ReorderContext } from '../strategies/reorder/ReorderStrategy.js';
|
|
4
|
+
import type { CandidateGenerationContext } from './candidate_context.js';
|
|
5
|
+
/**
|
|
6
|
+
* Builds candidate generation context for one loose item.
|
|
7
|
+
* @param context - Reorder context.
|
|
8
|
+
* @param containers - Working container layout.
|
|
9
|
+
* @param loose - Loose item reference.
|
|
10
|
+
* @returns Candidate generation context.
|
|
11
|
+
*/
|
|
12
|
+
export declare function candidate_context_for_loose(context: ReorderContext, containers: StabilizerContainer[], loose: LooseItemRef): CandidateGenerationContext;
|
|
13
|
+
//# sourceMappingURL=build_candidate_context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build_candidate_context.d.ts","sourceRoot":"","sources":["../../../src/core/candidates/build_candidate_context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAA;AAC7F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAA;AAC9E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAExE;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACvC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,mBAAmB,EAAE,EACjC,KAAK,EAAE,YAAY,GACpB,0BAA0B,CAU5B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds candidate generation context for one loose item.
|
|
3
|
+
* @param context - Reorder context.
|
|
4
|
+
* @param containers - Working container layout.
|
|
5
|
+
* @param loose - Loose item reference.
|
|
6
|
+
* @returns Candidate generation context.
|
|
7
|
+
*/
|
|
8
|
+
export function candidate_context_for_loose(context, containers, loose) {
|
|
9
|
+
return {
|
|
10
|
+
containers,
|
|
11
|
+
loose,
|
|
12
|
+
mode: context.waypoint_mode,
|
|
13
|
+
zones: context.waypoint_zones,
|
|
14
|
+
preserve_tie_block_organization: context.config.preserve_tie_block_organization,
|
|
15
|
+
milkrun_reserved_z_bands: context.milkrun_reserved_z_bands
|
|
16
|
+
};
|
|
17
|
+
}
|