@jetta/blocks-allocator 0.0.0-stage → 0.1.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +103 -2
  2. package/package.json +67 -5
  3. package/src/Allocation_Attempt.js +135 -0
  4. package/src/Allocation_Error_Handler.js +69 -0
  5. package/src/Allocation_Flow.js +162 -0
  6. package/src/Allocation_Optimization/Allocation_LP.js +150 -0
  7. package/src/Allocation_Optimization/Block_Allocator.js +129 -0
  8. package/src/Allocation_Optimization/Block_Layer_Order.js +50 -0
  9. package/src/Allocation_Optimization/Block_Potential_Weight.js +54 -0
  10. package/src/Allocation_Optimization/Chosen_Blocks_Stock_Cap.js +82 -0
  11. package/src/Allocation_Optimization/block_builder/Allocation_Item_Creator.js +37 -0
  12. package/src/Allocation_Optimization/block_builder/Block_Item_List_Validator.js +18 -0
  13. package/src/Allocation_Optimization/block_builder/Block_Wall_Builder.js +303 -0
  14. package/src/Allocation_Optimization/block_builder/Blocks_Builder.js +40 -0
  15. package/src/Allocation_Optimization/block_builder/Next_Block_Position.js +33 -0
  16. package/src/Allocation_Optimization/block_builder/Slot_Item_Assigner.js +45 -0
  17. package/src/Allocation_Optimization/block_builder/Stacking_Validation.js +30 -0
  18. package/src/Allocation_Optimization/block_builder/assert_tie_ratio_block_matches_orientation_below.js +44 -0
  19. package/src/Allocation_Optimization/block_builder/block_shape_stock.js +129 -0
  20. package/src/Allocation_Optimization/block_builder/exceptions/Empty_Block_Item_List_Exception.js +21 -0
  21. package/src/Allocation_Optimization/block_builder/exceptions/Invalid_Stacking_Exception.js +14 -0
  22. package/src/Allocation_Optimization/block_builder/exceptions/No_Suitable_Item_Exception.js +16 -0
  23. package/src/Allocation_Optimization/block_builder/exceptions/Restricted_Block_Exception.js +21 -0
  24. package/src/Allocation_Optimization/block_builder/should_omit_block_group_id.js +29 -0
  25. package/src/Allocation_Optimization/block_builder/snap_elevated_block_wall_items.js +34 -0
  26. package/src/Allocation_Optimization/block_builder/stacking_rules_input.js +52 -0
  27. package/src/Allocation_Optimization/cap_chosen_blocks_by_shape_stock.js +110 -0
  28. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Preparer.js +21 -0
  29. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Selector.js +55 -0
  30. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Threshold_Resolver.js +28 -0
  31. package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Thresholds.js +23 -0
  32. package/src/Allocation_Optimization/density_groups/Container_Utilization.js +67 -0
  33. package/src/Allocation_Optimization/density_groups/Density_Group_Partitioner.js +74 -0
  34. package/src/Allocation_Optimization/density_groups/Density_Group_Scheduler.js +168 -0
  35. package/src/Allocation_Optimization/density_groups/Density_Group_Stock.js +49 -0
  36. package/src/Allocation_Optimization/density_groups/Density_Groups_Strategy.js +26 -0
  37. package/src/Allocation_Optimization/density_groups/Item_Density_Calculator.js +20 -0
  38. package/src/Allocation_Optimization/density_groups/Lock_Weight_Ahead_Release.js +75 -0
  39. package/src/Allocation_Optimization/exceptions/Invalid_Item_Amount_Exception.js +17 -0
  40. package/src/Allocation_Optimization/exceptions/No_Valid_Allocation_Exception.js +14 -0
  41. package/src/Allocation_Optimization/exceptions/Optimization_Infeasible_Exception.js +14 -0
  42. package/src/Allocation_Optimization/functions/Measure_Reader.js +20 -0
  43. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Mode.js +25 -0
  44. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Strategies.js +8 -0
  45. package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Combination_Mode_Checkers.js +70 -0
  46. package/src/Allocation_Optimization/functions/Weight_Getter/Translation.js +22 -0
  47. package/src/Allocation_Optimization/functions/Weight_Getter/Variable_Weight_Getter.js +85 -0
  48. package/src/Allocation_Optimization/functions/Weight_Getter/constants.js +16 -0
  49. package/src/Allocation_Optimization/functions/measure_to_optimize.js +6 -0
  50. package/src/Allocation_Optimization/item_consumption_heuristic/Capacity_Bias_Item_Order.js +76 -0
  51. package/src/Allocation_Optimization/item_consumption_heuristic/Choose_Item_Heuristic_Context.js +63 -0
  52. package/src/Allocation_Optimization/item_consumption_heuristic/Item_Chooser.js +159 -0
  53. package/src/Allocation_Optimization/item_consumption_heuristic/Item_For_Slot_Chooser.js +49 -0
  54. package/src/Allocation_Optimization/item_consumption_heuristic/Slot_Compatible_Items_Finder.js +88 -0
  55. package/src/Allocation_Optimization/item_consumption_heuristic/Slots_Items_Assigner.js +182 -0
  56. package/src/Allocation_Optimization/item_consumption_heuristic/Stack_Slot_Calculator.js +87 -0
  57. package/src/Allocation_Optimization/item_consumption_heuristic/Weight_Slot_Distribution.js +72 -0
  58. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Empty_Slot_Exception.js +17 -0
  59. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Item_Taller_Than_Limit_Exception.js +21 -0
  60. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Available_Items_Exception.js +14 -0
  61. package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Slots_For_Items_Exception.js +14 -0
  62. package/src/Allocation_Optimization/lp_model/Block_Weight_Calculator.js +31 -0
  63. package/src/Allocation_Optimization/lp_model/LP_Data_Processor.js +42 -0
  64. package/src/Allocation_Optimization/lp_model/LP_Item_Slot_Assignment.js +93 -0
  65. package/src/Allocation_Optimization/lp_model/LP_Result_Mapper.js +47 -0
  66. package/src/Allocation_Optimization/lp_model/model_builder/Dimension_Range_Helper.js +49 -0
  67. package/src/Allocation_Optimization/lp_model/model_builder/Item_Assignment_Variables.js +133 -0
  68. package/src/Allocation_Optimization/lp_model/model_builder/LP_Model_Builder.js +132 -0
  69. package/src/Allocation_Optimization/lp_model/model_builder/exceptions/Missing_Item_Stock_Exception.js +18 -0
  70. package/src/Allocation_Optimization/lp_model/model_builder/goal_function/Goal_Function_Creator.js +83 -0
  71. package/src/Allocation_Optimization/lp_model/model_builder/item_dimension_hashes.js +31 -0
  72. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Block_Item_Amount_Restriction.js +53 -0
  73. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Coherence_Restriction.js +65 -0
  74. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Container_Supported_Weight_Restriction.js +42 -0
  75. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Exact_Pass_Amount_Restriction.js +62 -0
  76. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Group_Restriction.js +97 -0
  77. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Single_Item_Type_Restriction.js +79 -0
  78. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Space_Restriction.js +47 -0
  79. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Unavailable_Block_Restriction.js +27 -0
  80. package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Uniform_Block_Measure_Restriction.js +92 -0
  81. package/src/Allocation_Optimization/next_group_id_after_preloaded.js +30 -0
  82. package/src/Allocation_Optimization/preferential_blocks/Preferential_Block_Identifier.js +74 -0
  83. package/src/Allocation_Optimization/preferential_blocks/key_item/Key_Item_Mapper.js +49 -0
  84. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Almost_Unique_Item.js +31 -0
  85. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Cant_Stack_It_Self.js +68 -0
  86. package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Rule_Interface.js +26 -0
  87. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Intercalation_State.js +49 -0
  88. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter.js +33 -0
  89. package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter.js +20 -0
  90. package/src/Allocation_Optimization/tie_ratio/collect_tie_ratio_orientations_below_footprint.js +64 -0
  91. package/src/Allocation_Optimization/tie_ratio/filter_blocks_by_orientation.js +17 -0
  92. package/src/Allocation_Optimization/tie_ratio/find_orientation_below_space.js +77 -0
  93. package/src/Allocation_Optimization/tie_ratio/loose_on_block/allocated_item_penetrates_any.js +31 -0
  94. package/src/Allocation_Optimization/tie_ratio/loose_on_block/apply_loose_placement_to_allocated_item.js +94 -0
  95. package/src/Allocation_Optimization/tie_ratio/loose_on_block/axis_overlap_length.js +16 -0
  96. package/src/Allocation_Optimization/tie_ratio/loose_on_block/block_local_origin.js +18 -0
  97. package/src/Allocation_Optimization/tie_ratio/loose_on_block/box_fits_inside_container.js +39 -0
  98. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_allocated_item_at_placement.js +18 -0
  99. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_placement_on_generic_supporter.js +64 -0
  100. package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_slot_grid_from_cluster.js +66 -0
  101. package/src/Allocation_Optimization/tie_ratio/loose_on_block/compare_group_ids.js +20 -0
  102. package/src/Allocation_Optimization/tie_ratio/loose_on_block/container_with_pending_wall_items.js +26 -0
  103. package/src/Allocation_Optimization/tie_ratio/loose_on_block/empty_space_is_on_floor.js +16 -0
  104. package/src/Allocation_Optimization/tie_ratio/loose_on_block/finalize_loose_item_placement.js +58 -0
  105. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_best_generic_supporter_placement.js +58 -0
  106. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_next_free_slot_index.js +119 -0
  107. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_supporter_directly_below.js +51 -0
  108. package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_tie_ratio_supporter_cluster.js +57 -0
  109. package/src/Allocation_Optimization/tie_ratio/loose_on_block/footprint_xz_overlap_area.js +26 -0
  110. package/src/Allocation_Optimization/tie_ratio/loose_on_block/item_fits_supporter_slot.js +22 -0
  111. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_footprint_region_from_options.js +24 -0
  112. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_fits_inside_container.js +21 -0
  113. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_has_geometric_support.js +21 -0
  114. package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_on_block_slot_state.js +88 -0
  115. package/src/Allocation_Optimization/tie_ratio/loose_on_block/placement_coords_fit_inside_container.js +34 -0
  116. package/src/Allocation_Optimization/tie_ratio/loose_on_block/read_empilhar_area_igual_from_allocation_item.js +12 -0
  117. package/src/Allocation_Optimization/tie_ratio/loose_on_block/realigned_loose_geometry_gates.js +25 -0
  118. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_on_generic_supporter.js +65 -0
  119. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_placement_position.js +68 -0
  120. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_placement_y_at_slot.js +45 -0
  121. package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_without_tie_ratio_cluster.js +79 -0
  122. package/src/Allocation_Optimization/tie_ratio/loose_on_block/select_tie_ratio_slot_placement.js +84 -0
  123. package/src/Allocation_Optimization/tie_ratio/loose_on_block/slot_footprint_collision.js +105 -0
  124. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_cluster_selection.js +119 -0
  125. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_footprint_overlap.js +56 -0
  126. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_placement_plane.js +109 -0
  127. package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_supporter_predicate.js +23 -0
  128. package/src/Allocation_Optimization/tie_ratio/loose_on_block/try_tie_ratio_slot_placement.js +62 -0
  129. package/src/Allocation_Optimization/tie_ratio/snap_stacked_items_to_floor_footprints.js +138 -0
  130. package/src/Allocation_Optimization/tie_ratio/supporters_by_top_y_index.js +78 -0
  131. package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_below_empty_space.js +89 -0
  132. package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_from_group.js +48 -0
  133. package/src/Block_Management.js +34 -0
  134. package/src/Blocks_Preparation/Cube_Map_Function.js +27 -0
  135. package/src/Blocks_Wall_Allocation.js +3 -0
  136. package/src/IO/Answer_Status.js +4 -0
  137. package/src/IO/Output_Builder.js +35 -0
  138. package/src/IO/count_allocated_items.js +31 -0
  139. package/src/IO/create_error_response.js +62 -0
  140. package/src/IO/format_allocation_error_message.js +25 -0
  141. package/src/Item_Continuation_Lock.js +129 -0
  142. package/src/Item_Picking_Continuity.js +41 -0
  143. package/src/allocation_flow/chooser_session_state.js +21 -0
  144. package/src/allocation_flow/compound_probe_fallback.js +17 -0
  145. package/src/allocation_flow/container_remaining_capacity.js +23 -0
  146. package/src/allocation_flow/density_group_item_filter.js +31 -0
  147. package/src/allocation_flow/effective_item_fingerprint.js +14 -0
  148. package/src/allocation_flow/item_continuation_lock_gate.js +38 -0
  149. package/src/allocation_flow/no_space_left_recovery.js +48 -0
  150. package/src/allocation_flow/run_allocation_iteration.js +155 -0
  151. package/src/allocation_flow/space_skip_state.js +91 -0
  152. package/src/allocation_flow/try_no_space_left_recovery.js +50 -0
  153. package/src/exceptions/Invalid_Parameter_Exception.js +17 -0
  154. package/src/exceptions/Relational_Allocation_Incomplete_Exception.js +24 -0
  155. package/src/exceptions/Relational_Colocation_Violation_Exception.js +23 -0
  156. package/src/exceptions/Relational_Config_Mismatch_Exception.js +17 -0
  157. package/src/exceptions/There_Is_No_Block_Options_To_Allocate_Exception.js +14 -0
  158. package/src/index.js +6 -0
  159. package/src/input_preparation/Block_Formatter.js +179 -0
  160. package/src/input_preparation/Input_Creator.js +76 -0
  161. package/src/input_preparation/Input_State_Preparation.js +47 -0
  162. package/src/input_preparation/State_Builder.js +27 -0
  163. package/src/input_preparation/block_formatter/align_flush_axis_config.js +36 -0
  164. package/src/input_preparation/block_formatter/align_flush_axis_single_round.js +112 -0
  165. package/src/input_preparation/block_formatter/align_flush_stacked_slots.js +67 -0
  166. package/src/input_preparation/block_formatter/overlapped_slots.js +24 -0
  167. package/src/input_preparation/block_formatter/parallelepiped_shell.js +38 -0
  168. package/src/input_preparation/block_formatter/rectangle_coverage.js +112 -0
  169. package/src/input_preparation/block_formatter/shell_face_coverage.js +64 -0
  170. package/src/input_preparation/block_formatter/shell_snap_convergence.js +104 -0
  171. package/src/input_preparation/block_preparation/Block_Data_To_Object_Transformer.js +57 -0
  172. package/src/input_preparation/block_preparation/Block_Module_Name.js +17 -0
  173. package/src/input_preparation/block_preparation/Blocks_Creator.js +101 -0
  174. package/src/input_preparation/block_preparation/Blocksmith.js +19 -0
  175. package/src/input_preparation/block_preparation/block_modules/create_block_candidates.js +41 -0
  176. package/src/input_preparation/block_preparation/block_modules/manual_blocks.js +10 -0
  177. package/src/input_preparation/block_preparation/block_modules/module_registry.js +20 -0
  178. package/src/input_preparation/block_preparation/block_modules/run_creator.js +34 -0
  179. package/src/input_preparation/block_preparation/block_modules/single_item_blocks.js +12 -0
  180. package/src/input_preparation/block_preparation/block_modules/spiral_blocks.js +12 -0
  181. package/src/input_preparation/block_preparation/block_modules/tie_ratio_blocks.js +12 -0
  182. package/src/input_preparation/block_preparation/block_modules/tower_blocks.js +12 -0
  183. package/src/input_preparation/block_preparation/exceptions/Failed_To_Create_Block_Exception.js +14 -0
  184. package/src/input_preparation/block_preparation/exceptions/Failed_To_Retrieve_Block_Exception.js +17 -0
  185. package/src/input_preparation/block_preparation/exceptions/Missing_Object_Store_Exception.js +10 -0
  186. package/src/input_preparation/block_preparation/exceptions/No_Blocks_Were_Created_Exception.js +14 -0
  187. package/src/input_preparation/block_preparation/input/Input_Creator.js +96 -0
  188. package/src/input_preparation/block_preparation/manual_blocks/Manual_Blocks.js +95 -0
  189. package/src/input_preparation/build_empty_space_finder_options.js +43 -0
  190. package/src/input_preparation/item_preparation/Items_Reader.js +27 -0
  191. package/src/input_preparation/min_extents_from_items.js +29 -0
  192. package/src/input_preparation/stackability_index/Blocks_Stackability_Index_Calculator.js +58 -0
  193. package/src/input_preparation/stackability_index/Slots_Stackability_index_Calculator.js +28 -0
  194. package/src/input_preparation/stackability_index/Stackability_Input_Creator.js +27 -0
  195. package/src/input_preparation/stackability_index/stackability_index_pop_stack.js +81 -0
  196. package/src/input_preparation/stacking_constraints/Weight_Stacking_Validation.js +15 -0
  197. package/src/lp_optimizer_result_status.js +20 -0
  198. package/src/messages/Allocator_Message.js +42 -0
  199. package/src/messages/resolve_error_message_entry.js +57 -0
  200. package/src/models/Allocated_Item.js +136 -0
  201. package/src/models/Allocation_Item.js +219 -0
  202. package/src/models/Block.js +198 -0
  203. package/src/models/Cargo_Profile.js +418 -0
  204. package/src/models/Preloaded_Allocated_Item.js +132 -0
  205. package/src/models/Slot.js +67 -0
  206. package/src/models/Stacking_Rules.js +58 -0
  207. package/src/models/auxiliaryFunctions/Available_Block_Module_List_Creator.js +9 -0
  208. package/src/models/auxiliaryFunctions/Measure_Translator.js +24 -0
  209. package/src/models/auxiliaryFunctions/item_json_reader.js +44 -0
  210. package/src/models/item_json_reader.js +71 -0
  211. package/src/models/placed_item_record.js +70 -0
  212. package/src/models/preloaded_rotation_helpers.js +38 -0
  213. package/src/models/slots_have_same_measure.js +45 -0
  214. package/src/models/transport/Container.js +162 -0
  215. package/src/models/transport/Transport.js +62 -0
  216. package/src/models/transport/build_stacking_feasibility_checker.js +64 -0
  217. package/src/models/transport/container_stacking_checkpoint.js +42 -0
  218. package/src/models/transport/factory/Container_Factory.js +46 -0
  219. package/src/models/transport/factory/Corner_Casting_Factory.js +62 -0
  220. package/src/models/transport/factory/Previously_Allocated_Item_Factory.js +28 -0
  221. package/src/models/transport/factory/Transport_Factory.js +13 -0
  222. package/src/models/transport/items_for_empty_space_finder.js +91 -0
  223. package/src/models/transport/resolve_container_stacking_inputs.js +23 -0
  224. package/src/models/transport/stacking_input_from_wire.js +58 -0
  225. package/src/optimizer_connection_errors.js +50 -0
  226. package/src/relational/Relational_Error_Codes.js +7 -0
  227. package/src/relational/finalize_relational_allocation.js +20 -0
  228. package/src/relational/has_relational_items.js +11 -0
  229. package/src/relational/is_relational_error_code.js +15 -0
  230. package/src/relational/resolve_relational_container_sequences.js +29 -0
  231. package/src/run_core_allocation.js +118 -0
  232. package/src/space_and_block_chooser/Space_And_Blocks_Chooser.js +115 -0
  233. package/src/space_and_block_chooser/blocks_filters/Block_Filter_Interface.js +19 -0
  234. package/src/space_and_block_chooser/blocks_filters/Filter_Runner.js +46 -0
  235. package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Block_With_Overlapped_Slots_Filter.js +14 -0
  236. package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Initial_Blocks_Filter_List.js +19 -0
  237. package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Blocks_Bigger_Than_Space_Filter.js +17 -0
  238. package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Post_Selection_Filter_List.js +9 -0
  239. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Insuficient_Items_Filter.js +81 -0
  240. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Pre_Selection_Filter_List.js +8 -0
  241. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Blocks_Lower_Than_Max_Tower_Height.js +23 -0
  242. package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Max_Tower_Height.js +82 -0
  243. package/src/space_and_block_chooser/build_allocated_item_snapshots.js +19 -0
  244. package/src/space_and_block_chooser/compound_first_empty_space_branch.js +61 -0
  245. package/src/space_and_block_chooser/compound_first_with_leftover_fill.js +142 -0
  246. package/src/space_and_block_chooser/compound_first_without_leftover_fill.js +56 -0
  247. package/src/space_and_block_chooser/empty_spaces_where_post_selection_keeps_blocks.js +83 -0
  248. package/src/space_and_block_chooser/exceptions/Invalid_Space_To_Allocate_Exception.js +14 -0
  249. package/src/space_and_block_chooser/leftover_space_memory.js +113 -0
  250. package/src/space_and_block_chooser/leftover_unitary_blocks.js +153 -0
  251. package/src/space_and_block_chooser/leftover_unitary_empty_spaces.js +135 -0
  252. package/src/space_and_block_chooser/probe_set_pool.js +35 -0
  253. package/src/space_and_block_chooser/run_space_and_block_selection_attempt.js +88 -0
  254. package/src/tools/Array_Validator.js +6 -0
  255. package/src/tools/Clone.js +27 -0
  256. package/src/tools/Hash.js +8 -0
  257. package/src/tools/Rounder.js +5 -0
  258. package/src/tools/String_To_Boolean.js +12 -0
  259. package/src/tools/cargo_profile/Cargo_Profile_Field_Value_Resolver.js +44 -0
  260. package/src/tools/compact_items_with_stock.js +9 -0
  261. package/src/tools/mm_to_allocation_domain.js +14 -0
  262. package/src/tracing/Allocation_Tracer.js +52 -0
  263. package/src/tracing/Trace_Context.js +18 -0
  264. package/src/tracing/trace_outcome.js +18 -0
  265. package/src/tracing/traced_step.js +57 -0
  266. package/src/validation/Item_Continuation_Lock_Flag.js +52 -0
  267. package/src/validation/Item_Validation.js +29 -0
  268. package/src/validation/Relational_Colocation_Validator.js +60 -0
  269. package/src/validation/Relational_Completeness_Validator.js +146 -0
  270. package/src/validation/Relational_Continuation_Lock_Validation.js +37 -0
  271. package/src/validation/Relational_Proportional_Normalizer.js +194 -0
  272. package/src/validation/Validation.js +9 -0
  273. package/src/validation/Validation_Runner.js +20 -0
  274. package/src/validation/exceptions/Invalid_Block_Module_Config_Exception.js +14 -0
  275. package/src/validation/exceptions/Invalid_Input_Exception.js +14 -0
  276. package/src/validation/exceptions/Invalid_Input_Type_Exception.js +14 -0
  277. package/src/validation/schemas/allocated_item_schema.js +18 -0
  278. package/src/validation/schemas/allocation_request_schema.js +178 -0
  279. package/src/validation/schemas/container_row_schema.js +16 -0
  280. package/src/validation/schemas/item_schema.js +60 -0
  281. package/src/validation/schemas/transport_env_schema.js +19 -0
  282. package/src/validation/validate_block_module_config.js +147 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Finds the density group index that contains the given item id.
3
+ * @param {Map<number, Set<string>>} groups - Group index to item id set.
4
+ * @param {number} group_count - Total number of groups.
5
+ * @param {string} item_id - Item identifier.
6
+ * @returns {number|null}
7
+ */
8
+ function find_group_index_for_item_id(groups, group_count, item_id)
9
+ {
10
+ for (let group_index = 0; group_index < group_count; group_index++)
11
+ {
12
+ const group_ids = groups.get(group_index)
13
+ if (group_ids && group_ids.has(item_id))
14
+ {
15
+ return group_index
16
+ }
17
+ }
18
+
19
+ return null
20
+ }
21
+
22
+ /**
23
+ * Returns density group indices that still have at least one item with stock.
24
+ * @param {Map<number, Set<string>>} groups - Group index to item id set.
25
+ * @param {number} group_count - Total number of groups.
26
+ * @param {object[]} item_list - Master item list.
27
+ * @returns {number[]}
28
+ */
29
+ function get_groups_with_stock(groups, group_count, item_list)
30
+ {
31
+ const groups_with_stock = []
32
+
33
+ for (let group_index = 0; group_index < group_count; group_index++)
34
+ {
35
+ const group_ids = groups.get(group_index)
36
+ const has_stock = item_list.some(
37
+ item => group_ids.has(item.get_id()) && item.get_amount() > 0
38
+ )
39
+
40
+ if (has_stock)
41
+ {
42
+ groups_with_stock.push(group_index)
43
+ }
44
+ }
45
+
46
+ return groups_with_stock
47
+ }
48
+
49
+ module.exports = { find_group_index_for_item_id, get_groups_with_stock }
@@ -0,0 +1,26 @@
1
+ const DENSITY_GROUPS_STRATEGY = Object.freeze({
2
+ ROUND_ROBIN: 'round_robin',
3
+ ADAPTIVE: 'adaptive',
4
+ })
5
+
6
+ const VALID_DENSITY_GROUP_STRATEGIES = Object.freeze(Object.values(DENSITY_GROUPS_STRATEGY))
7
+
8
+ /**
9
+ * Maps raw config input to a density group strategy constant.
10
+ * @param {unknown} raw - Raw strategy value from cargo profile config.
11
+ * @returns {typeof DENSITY_GROUPS_STRATEGY.ROUND_ROBIN | typeof DENSITY_GROUPS_STRATEGY.ADAPTIVE}
12
+ */
13
+ function normalize_density_groups_strategy(raw)
14
+ {
15
+ if (raw === DENSITY_GROUPS_STRATEGY.ADAPTIVE)
16
+ {
17
+ return DENSITY_GROUPS_STRATEGY.ADAPTIVE
18
+ }
19
+ return DENSITY_GROUPS_STRATEGY.ROUND_ROBIN
20
+ }
21
+
22
+ module.exports = {
23
+ DENSITY_GROUPS_STRATEGY,
24
+ VALID_DENSITY_GROUP_STRATEGIES,
25
+ normalize_density_groups_strategy,
26
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Computes item density (weight / volume) for SKU-level grouping.
3
+ * @param {object} item - Item with get_weight, get_width, get_height, get_length, get_id.
4
+ * @returns {{ item_id: string, density: number }}
5
+ */
6
+ function calculate_item_density(item)
7
+ {
8
+ const weight = item.get_weight()
9
+ const volume = item.get_width() * item.get_height() * item.get_length()
10
+ const item_id = item.get_id()
11
+
12
+ if (!Number.isFinite(weight) || weight < 0 || volume <= 0)
13
+ {
14
+ return { item_id, density: Number.POSITIVE_INFINITY }
15
+ }
16
+
17
+ return { item_id, density: weight / volume }
18
+ }
19
+
20
+ module.exports = { calculate_item_density }
@@ -0,0 +1,75 @@
1
+ const Cargo_Profile = require('../../models/Cargo_Profile')
2
+ const { DENSITY_GROUPS_STRATEGY } = require('./Density_Groups_Strategy')
3
+ const { get_weight_ahead_threshold } = require('./Adaptive_Density_Group_Threshold_Resolver')
4
+ const { get_weight_utilization, get_space_utilization } = require('./Container_Utilization')
5
+
6
+ /**
7
+ * Returns whether the continuation lock should release so adaptive density groups can expose lighter SKUs.
8
+ * @param {object} container - Current container.
9
+ * @param {object} density_scheduler - Density group scheduler.
10
+ * @param {object[]} item_list - Master item list.
11
+ * @param {object} locked_item - Locked item instance.
12
+ * @returns {boolean}
13
+ */
14
+ function should_release_lock_for_weight_ahead(container, density_scheduler, item_list, locked_item)
15
+ {
16
+ const gap = get_weight_utilization(container) - get_space_utilization(container)
17
+ if (gap <= get_weight_ahead_threshold())
18
+ {
19
+ return false
20
+ }
21
+
22
+ const groups_with_stock = density_scheduler.get_groups_with_stock(item_list)
23
+ if (groups_with_stock.length === 0)
24
+ {
25
+ return false
26
+ }
27
+
28
+ const lowest_density_group = Math.min(...groups_with_stock)
29
+ const locked_group = density_scheduler.find_group_index_for_item_id(locked_item.get_id())
30
+ if (locked_group === null)
31
+ {
32
+ return false
33
+ }
34
+
35
+ return locked_group > lowest_density_group
36
+ }
37
+
38
+ /**
39
+ * Releases the lock when weight is ahead and the locked SKU is not in the lightest density band.
40
+ * @param {object} container - Current container.
41
+ * @param {object|null} density_scheduler - Density group scheduler, if enabled.
42
+ * @param {object} item_lock - Item continuation lock instance.
43
+ * @param {object[]} item_list - Master item list.
44
+ * @param {object|null} locked_item - Currently locked item, if any.
45
+ * @returns {object|null} Locked item after optional release.
46
+ */
47
+ function apply_weight_ahead_lock_release(container, density_scheduler, item_lock, item_list, locked_item)
48
+ {
49
+ if (!locked_item || !density_scheduler)
50
+ {
51
+ return locked_item
52
+ }
53
+
54
+ if (Cargo_Profile.density_groups_strategy() !== DENSITY_GROUPS_STRATEGY.ADAPTIVE)
55
+ {
56
+ return locked_item
57
+ }
58
+
59
+ const should_release = should_release_lock_for_weight_ahead(
60
+ container,
61
+ density_scheduler,
62
+ item_list,
63
+ locked_item
64
+ )
65
+
66
+ if (!should_release)
67
+ {
68
+ return locked_item
69
+ }
70
+
71
+ item_lock.release_for_density_balance()
72
+ return null
73
+ }
74
+
75
+ module.exports = { apply_weight_ahead_lock_release }
@@ -0,0 +1,17 @@
1
+ const { build_message_entry } = require('../../messages/resolve_error_message_entry')
2
+ const { ALLOCATOR_MESSAGE } = require('../../messages/Allocator_Message')
3
+
4
+ class Invalid_Item_Amount_Exception extends Error
5
+ {
6
+ /**
7
+ * @param {string|number} item
8
+ */
9
+ constructor(item)
10
+ {
11
+ const message_key = ALLOCATOR_MESSAGE.INVALID_ITEM_AMOUNT
12
+ super(message_key)
13
+ this.message_entry = build_message_entry(message_key, [String(item)])
14
+ }
15
+ }
16
+
17
+ module.exports = Invalid_Item_Amount_Exception
@@ -0,0 +1,14 @@
1
+ const { build_message_entry } = require('../../messages/resolve_error_message_entry')
2
+ const { ALLOCATOR_MESSAGE } = require('../../messages/Allocator_Message')
3
+
4
+ class No_Valid_Allocation_Exception extends Error
5
+ {
6
+ constructor()
7
+ {
8
+ const message_key = ALLOCATOR_MESSAGE.NO_VALID_ALLOCATION
9
+ super(message_key)
10
+ this.message_entry = build_message_entry(message_key)
11
+ }
12
+ }
13
+
14
+ module.exports = No_Valid_Allocation_Exception
@@ -0,0 +1,14 @@
1
+ const { build_message_entry } = require('../../messages/resolve_error_message_entry')
2
+ const { ALLOCATOR_MESSAGE } = require('../../messages/Allocator_Message')
3
+
4
+ class Optimization_Infeasible_Exception extends Error
5
+ {
6
+ constructor()
7
+ {
8
+ const message_key = ALLOCATOR_MESSAGE.OPTIMIZATION_INFEASIBLE
9
+ super(message_key)
10
+ this.message_entry = build_message_entry(message_key)
11
+ }
12
+ }
13
+
14
+ module.exports = Optimization_Infeasible_Exception
@@ -0,0 +1,20 @@
1
+ const Cargo_Profile = require('../../models/Cargo_Profile')
2
+ const measure_to_optimize = require('./measure_to_optimize')
3
+
4
+ function read_measure_to_be_optimized()
5
+ {
6
+ const config = Cargo_Profile.measure_to_optimize()
7
+ switch (config.toLowerCase())
8
+ {
9
+ case measure_to_optimize.LENGTH:
10
+ return measure_to_optimize.LENGTH
11
+ case measure_to_optimize.WIDTH:
12
+ return measure_to_optimize.WIDTH
13
+ default:
14
+ return measure_to_optimize.WIDTH
15
+ }
16
+ }
17
+
18
+ module.exports = {
19
+ read_measure_to_be_optimized
20
+ }
@@ -0,0 +1,25 @@
1
+
2
+ const Cargo_Profile = require('../../../models/Cargo_Profile')
3
+ const { mode_checks } = require('./Measure_Combination_Mode_Checkers')
4
+
5
+ /*
6
+ * Determines the computation mode based on the block variable weight configuration.
7
+ * @returns {string} The computation mode.
8
+ */
9
+ function get_mode()
10
+ {
11
+ const config = Cargo_Profile.block_variable_weight_config()
12
+
13
+ const default_value = 'volume'
14
+
15
+ if (!config || config.length <= 1)
16
+ {
17
+ return default_value
18
+ }
19
+
20
+ const found = mode_checks.find(item => item.check(config))
21
+
22
+ return found ? found.mode : default_value
23
+ }
24
+
25
+ module.exports = get_mode
@@ -0,0 +1,8 @@
1
+ const strategies = {
2
+ volume: block => block.get_volume(),
3
+ height_length: block => block.get_length() * block.get_height(),
4
+ length_width: block => block.get_length() * block.get_width(),
5
+ height_width: block => block.get_height() * block.get_width(),
6
+ }
7
+
8
+ module.exports = strategies
@@ -0,0 +1,70 @@
1
+ const { DIMENSIONS } = require('./constants')
2
+ const { includes_key_or_translation } = require('./Translation')
3
+
4
+ /**
5
+ * Checks if a configuration array contains all the given keys, considering translations.
6
+ * @param {string[]} config - The configuration array from Cargo Profile.
7
+ * @param {...string} keys - The dimension keys to check for.
8
+ * @returns {boolean}
9
+ */
10
+ const has = (config, ...keys) => keys.every( key => includes_key_or_translation(config, key) )
11
+
12
+ const { HEIGHT, LENGTH, WIDTH } = DIMENSIONS
13
+
14
+ /**
15
+ * @constant {object} volume_check
16
+ * @property {function(string[]): boolean} check - Function to check if the config includes HEIGHT, LENGTH, and WIDTH.
17
+ * @property {string} mode - The mode name for volume.
18
+ * @augments ModeCheck
19
+ */
20
+ const volume_check = {
21
+ check: config => has(config, HEIGHT, LENGTH, WIDTH),
22
+ mode: 'volume',
23
+ }
24
+
25
+ /**
26
+ * @constant {object} height_length_check
27
+ * @property {function(string[]): boolean} check - Function to check if the config includes HEIGHT and LENGTH, but not WIDTH.
28
+ * @property {string} mode - The mode name for height and length.
29
+ * @augments ModeCheck
30
+ */
31
+ const height_length_check = {
32
+ check: config => has(config, HEIGHT, LENGTH) && !has(config, WIDTH),
33
+ mode: 'height_length',
34
+ }
35
+
36
+ /**
37
+ * @constant {object} length_width_check
38
+ * @property {function(string[]): boolean} check - Function to check if the config includes LENGTH and WIDTH, but not HEIGHT.
39
+ * @property {string} mode - The mode name for length and width.
40
+ * @augments ModeCheck
41
+ */
42
+ const length_width_check = {
43
+ check: config => has(config, LENGTH, WIDTH) && !has(config, HEIGHT),
44
+ mode: 'length_width',
45
+ }
46
+
47
+ /**
48
+ * @constant {object} height_width_check
49
+ * @property {function(string[]): boolean} check - Function to check if the config includes HEIGHT and WIDTH, but not LENGTH.
50
+ * @property {string} mode - The mode name for height and width.
51
+ * @augments ModeCheck
52
+ */
53
+ const height_width_check = {
54
+ check: config => has(config, HEIGHT, WIDTH) && !has(config, LENGTH),
55
+ mode: 'height_width',
56
+ }
57
+
58
+ /**
59
+ * @typedef {object} ModeCheck
60
+ * @property {function(string[]): boolean} check - A function that takes a configuration array and returns true if the configuration matches this mode.
61
+ * @property {string} mode - The string identifier for the mode.
62
+ */
63
+ const mode_checks = [
64
+ volume_check,
65
+ height_length_check,
66
+ length_width_check,
67
+ height_width_check
68
+ ]
69
+
70
+ module.exports = { mode_checks }
@@ -0,0 +1,22 @@
1
+ const {TRANSLATIONS} = require('./constants')
2
+
3
+ /**
4
+ * Translates a given key using predefined translations.
5
+ * If no translation is found, the original key is returned.
6
+ * @param {string} key - The key to translate.
7
+ * @returns {string} The translated key or the original key if no translation exists.
8
+ */
9
+ const translate = key => (TRANSLATIONS[key] || key)
10
+
11
+ /**
12
+ * Checks if a configuration array includes a specific key or its translation.
13
+ * @param {string[]} config - The configuration array.
14
+ * @param {string} key - The key to check for.
15
+ * @returns {boolean} True if the key or its translation is found, false otherwise.
16
+ */
17
+ const includes_key_or_translation = (config, key) =>
18
+ {
19
+ return config.includes(key) || config.includes(translate(key))
20
+ }
21
+
22
+ module.exports = {includes_key_or_translation}
@@ -0,0 +1,85 @@
1
+ const Cargo_Profile = require('../../../models/Cargo_Profile')
2
+ const round = require('../../../tools/Rounder')
3
+ const get_mode = require('./Measure_Cobination_Mode')
4
+
5
+ const should_prefer_same_measure_items_block = () => Cargo_Profile.prefer_same_measure_slot_blocks()
6
+
7
+ const compute_weight = {
8
+ volume: block => block.get_volume(),
9
+ height_length: block => block.get_height() * block.get_length(),
10
+ length_width: block => block.get_length() * block.get_width(),
11
+ height_width: block => block.get_height() * block.get_width(),
12
+ }
13
+
14
+ const get_item_amount_untie = block => block.get_slot_list().length * Cargo_Profile.untie_by_quantity_multiplier()
15
+
16
+ /**
17
+ * Calculates a bonus weight based on the measure combination mode.
18
+ * The specific calculation depends on the mode returned by `get_mode()`.
19
+ * @param {Block} block - The block object for which to calculate the bonus.
20
+ * @returns {number} The measure combination bonus weight.
21
+ */
22
+ const get_measure_combination_bonus = (block) =>
23
+ {
24
+ const mode = get_mode()
25
+ const computer = compute_weight[mode]
26
+ if (computer)
27
+ {
28
+ return computer(block) / 10
29
+ }
30
+ return 0
31
+ }
32
+
33
+ /**
34
+ * Calculates a bonus weight based on the block's stackability index.
35
+ * @param {Block} block - The block object for which to calculate the bonus.
36
+ * @returns {number} The stackability bonus weight.
37
+ */
38
+ const get_stackability_bonus = block => block.get_stackability_index()
39
+
40
+ /**
41
+ * Calculates a bonus weight if the block is marked as a "preference" block.
42
+ * Returns preferential_blocks_bonus(default 5) if preferred, otherwise 0.
43
+ * @param {Block} block - The block object for which to calculate the bonus.
44
+ * @returns {number} The preference bonus weight.
45
+ */
46
+ const get_preference_bonus = block => (block.is_preference() ? Cargo_Profile.preferential_blocks_bonus() : 0)
47
+
48
+ /**
49
+ * Calculates a bonus weight if the block's slots have the same measures and
50
+ * either same-measure preference flag is true.
51
+ * @param {Block} block - The block object for which to calculate the bonus.
52
+ * @returns {number} The same item measures bonus weight.
53
+ */
54
+ function get_same_item_measures_bonus (block)
55
+ {
56
+ const has_same_measures = block.is_slots_of_same_measure()
57
+ const same_item_measures_bonus = Cargo_Profile.same_item_measures_bonus()
58
+ return should_prefer_same_measure_items_block() && has_same_measures ? same_item_measures_bonus : 0
59
+ }
60
+
61
+
62
+ // --- Main Exported Function ---
63
+
64
+ /**
65
+ * Calculates a custom weight for a block based on various factors.
66
+ * @param {object} block - The block to be evaluated.
67
+ * @returns {number} The calculated custom weight.
68
+ */
69
+ function get_custom_weight(block)
70
+ {
71
+
72
+ const weight_components = [
73
+ get_measure_combination_bonus(block),
74
+ get_stackability_bonus(block),
75
+ get_same_item_measures_bonus(block),
76
+ get_preference_bonus(block),
77
+ get_item_amount_untie(block)
78
+ ]
79
+
80
+ const total_weight = weight_components.reduce((sum, value) => sum + value, 0)
81
+
82
+ return round(total_weight)
83
+ }
84
+
85
+ module.exports = get_custom_weight
@@ -0,0 +1,16 @@
1
+ const DIMENSIONS = {
2
+ HEIGHT: 'height',
3
+ LENGTH: 'length',
4
+ WIDTH: 'width',
5
+ }
6
+
7
+ const TRANSLATIONS = {
8
+ [DIMENSIONS.HEIGHT]: 'altura',
9
+ [DIMENSIONS.LENGTH]: 'comprimento',
10
+ [DIMENSIONS.WIDTH]: 'largura',
11
+ }
12
+
13
+ module.exports = {
14
+ DIMENSIONS,
15
+ TRANSLATIONS,
16
+ }
@@ -0,0 +1,6 @@
1
+ const measure_to_optimize = {
2
+ LENGTH :'length',
3
+ WIDTH : 'width'
4
+ }
5
+
6
+ module.exports = measure_to_optimize
@@ -0,0 +1,76 @@
1
+ const { get_weight_utilization, get_space_utilization } = require('../density_groups/Container_Utilization')
2
+ const { calculate_item_density } = require('../density_groups/Item_Density_Calculator')
3
+
4
+ /**
5
+ * Compares two items by density for stable sorting.
6
+ * @param {object} left_item
7
+ * @param {object} right_item
8
+ * @returns {number}
9
+ */
10
+ function compare_by_density_ascending(left_item, right_item)
11
+ {
12
+ const left_density = calculate_item_density(left_item).density
13
+ const right_density = calculate_item_density(right_item).density
14
+ if (left_density !== right_density)
15
+ {
16
+ return left_density - right_density
17
+ }
18
+ return String(left_item.get_id()).localeCompare(String(right_item.get_id()))
19
+ }
20
+
21
+ /**
22
+ * Whether the container exposes the accessors needed for utilization metrics.
23
+ * @param {object} container
24
+ * @returns {boolean}
25
+ */
26
+ function container_supports_utilization(container)
27
+ {
28
+ const required_methods = [
29
+ 'get_allocated_items',
30
+ 'get_width',
31
+ 'get_height',
32
+ 'get_length'
33
+ ]
34
+ return required_methods.every((method_name) =>
35
+ typeof container[method_name] === 'function'
36
+ )
37
+ }
38
+
39
+ /**
40
+ * Reorders compatible items using container weight vs space utilization.
41
+ * @param {object[]} item_list - Candidate items.
42
+ * @param {object|null|undefined} container - Container with allocated items.
43
+ * @returns {object[]} Same items, possibly reordered.
44
+ */
45
+ function order_items_by_capacity_bias(item_list, container)
46
+ {
47
+ if (!container || item_list.length <= 1)
48
+ {
49
+ return item_list
50
+ }
51
+
52
+ if (!container_supports_utilization(container))
53
+ {
54
+ return item_list
55
+ }
56
+
57
+ const gap = get_weight_utilization(container) - get_space_utilization(container)
58
+ if (gap === 0)
59
+ {
60
+ return item_list
61
+ }
62
+
63
+ const sorted_items = item_list.slice()
64
+ if (gap > 0)
65
+ {
66
+ sorted_items.sort(compare_by_density_ascending)
67
+ return sorted_items
68
+ }
69
+
70
+ sorted_items.sort((left_item, right_item) =>
71
+ compare_by_density_ascending(right_item, left_item)
72
+ )
73
+ return sorted_items
74
+ }
75
+
76
+ module.exports = { order_items_by_capacity_bias }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Builds a container stub for tests and legacy callers that only pass height_limit.
3
+ * @param {number} height_limit - Stack height cap.
4
+ * @returns {object} Minimal container with get_height and permissive is_a_valid_stacking.
5
+ */
6
+ function create_height_limit_container_stub(height_limit)
7
+ {
8
+ return {
9
+ get_height: () => height_limit,
10
+ is_a_valid_stacking: () => true
11
+ }
12
+ }
13
+
14
+ /**
15
+ * Resolves slot, container, and item_position for choose_item heuristic path.
16
+ * @param {object} data - Same bag as choose_item.
17
+ * @returns {{ slot: object, container: object, item_position: { x: number, y: number, z: number } }}
18
+ */
19
+ function resolve_choose_item_heuristic_context(data)
20
+ {
21
+ const slot = data.slot ?? data.block_slot
22
+ if (!slot)
23
+ {
24
+ throw new Error('choose_item heuristic requires data.slot or data.block_slot')
25
+ }
26
+ let container = data.container
27
+ if (!container && data.height_limit != null)
28
+ {
29
+ container = create_height_limit_container_stub(data.height_limit)
30
+ }
31
+ if (!container)
32
+ {
33
+ throw new Error('choose_item heuristic requires data.container or data.height_limit')
34
+ }
35
+ const item_position = data.item_position
36
+ return { slot, container, item_position }
37
+ }
38
+
39
+ /**
40
+ * Human-readable slot label for exception messages.
41
+ * @param {object} slot - Slot with optional to_string or get_x/get_y/get_z.
42
+ * @returns {string}
43
+ */
44
+ function format_slot_label_for_exception(slot)
45
+ {
46
+ if (typeof slot.to_string === 'function')
47
+ {
48
+ return slot.to_string()
49
+ }
50
+ const x = slot.get_x?.()
51
+ const y = slot.get_y?.()
52
+ const z = slot.get_z?.()
53
+ if (x !== undefined && y !== undefined && z !== undefined)
54
+ {
55
+ return `${x};${y};${z}`
56
+ }
57
+ return 'slot'
58
+ }
59
+
60
+ module.exports = {
61
+ resolve_choose_item_heuristic_context,
62
+ format_slot_label_for_exception
63
+ }