@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,21 @@
1
+ const { build_message_entry } = require('../../../messages/resolve_error_message_entry')
2
+ const { ALLOCATOR_MESSAGE } = require('../../../messages/Allocator_Message')
3
+
4
+ class Restricted_Block_Exception extends Error
5
+ {
6
+ /**
7
+ * @param {{ id: string|number, restrict_to: number }} block_to_restrict
8
+ */
9
+ constructor(block_to_restrict)
10
+ {
11
+ const message_key = ALLOCATOR_MESSAGE.RESTRICTED_BLOCK
12
+ super(message_key)
13
+ this.message_entry = build_message_entry(
14
+ message_key,
15
+ [String(block_to_restrict.id), String(block_to_restrict.restrict_to)]
16
+ )
17
+ this.block_to_restrict = block_to_restrict
18
+ }
19
+ }
20
+
21
+ module.exports = Restricted_Block_Exception
@@ -0,0 +1,29 @@
1
+ const math = require('@jetta/number-compare')
2
+
3
+ const FULL_TIE_RATIO_SLOT_COUNT = 5
4
+ const FLOOR_HEIGHT_Y = 0
5
+
6
+ /**
7
+ * Whether a built block should omit a shared group id.
8
+ * Single-slot leftovers and remainder tie-ratio blocks (fewer than five slots)
9
+ * stay ungrouped. Full 3_2/2_3 walls keep a shared id only on the floor.
10
+ * Generic compounds always keep a shared id.
11
+ * @param {{ get_slot_list: () => unknown[], is_tie_ratio_block?: () => boolean }} block
12
+ * @param {number} [wall_height_y=0] - Empty-space y (height) of the wall being built.
13
+ * @returns {boolean}
14
+ */
15
+ function should_omit_block_group_id(block, wall_height_y = FLOOR_HEIGHT_Y)
16
+ {
17
+ const slot_count = block.get_slot_list().length
18
+ if (slot_count === 1)
19
+ {
20
+ return true
21
+ }
22
+ if (typeof block.is_tie_ratio_block === 'function' && block.is_tie_ratio_block())
23
+ {
24
+ return slot_count < FULL_TIE_RATIO_SLOT_COUNT || math.gt(wall_height_y, FLOOR_HEIGHT_Y)
25
+ }
26
+ return false
27
+ }
28
+
29
+ module.exports = should_omit_block_group_id
@@ -0,0 +1,34 @@
1
+ const math = require('@jetta/number-compare')
2
+ const Cargo_Profile = require('../../models/Cargo_Profile')
3
+ const snap_stacked_items_to_floor_footprints = require(
4
+ '../tie_ratio/snap_stacked_items_to_floor_footprints'
5
+ )
6
+
7
+ /**
8
+ * Snaps stacked wall items onto unique floor (x, z) footprints.
9
+ * @param {object[]} item_in_block_list
10
+ * @param {object} wall_data
11
+ * @param {object[]} pending_wall_allocated_items
12
+ * @returns {object[]}
13
+ */
14
+ function snap_elevated_block_wall_items(item_in_block_list, wall_data, pending_wall_allocated_items)
15
+ {
16
+ if (!Cargo_Profile.snap_stacked_items_to_floor_footprints())
17
+ {
18
+ return item_in_block_list
19
+ }
20
+ if (!math.gt(wall_data.space_to_allocate.get_y(), 0))
21
+ {
22
+ return item_in_block_list
23
+ }
24
+ const allocated_items = collect_allocated_items(wall_data, pending_wall_allocated_items)
25
+ return snap_stacked_items_to_floor_footprints(item_in_block_list, allocated_items)
26
+ }
27
+
28
+ function collect_allocated_items(wall_data, pending_wall_allocated_items)
29
+ {
30
+ const from_container = wall_data.container.get_allocated_items?.() ?? []
31
+ return from_container.concat(pending_wall_allocated_items)
32
+ }
33
+
34
+ module.exports = snap_elevated_block_wall_items
@@ -0,0 +1,52 @@
1
+ const str_to_bool = require('../../tools/String_To_Boolean')
2
+
3
+ /**
4
+ * Builds stacking-rules payload for {@link StackingFeasibilityChecker} from stacking metadata.
5
+ * @param {object} item_stacking_info - Output shape from `build_stacking_info`.
6
+ * @param {object} json - Item record with at least `stackingUnit`.
7
+ * @returns {object}
8
+ */
9
+ function build_stacking_rules_from_info(item_stacking_info, json)
10
+ {
11
+ const restrictions = item_stacking_info.restrictions ?? {}
12
+ return {
13
+ enableStackSameAreaOnly: str_to_bool(restrictions.empilharAreaIgual),
14
+ enableStackSameItemOnly: str_to_bool(restrictions.empilharItemIgual),
15
+ maximumNumberOfItemsAbove: item_stacking_info.max_stacking,
16
+ weight: item_stacking_info.weight,
17
+ enableMaximumNumberOfItemsAbove: is_maximum_stacking_enabled(json),
18
+ enableMaximumStackingWeight: is_supported_weight_enabled(json),
19
+ maximumStackingWeight: item_stacking_info.supported_weight,
20
+ enableOnlyAllowedFamilies: str_to_bool(restrictions.empilharFamilias),
21
+ allowedFamilies: item_stacking_info.supported_families,
22
+ family: item_stacking_info.stacking_family,
23
+ priority: item_stacking_info.priority ?? -666,
24
+ enableStackonlySamePriorities: str_to_bool(restrictions.empilharPrioridades)
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @param {object} item - Object exposing `get_stacking_info()` and `get_json()`.
30
+ * @returns {object}
31
+ */
32
+ function get_stacking_rules_input(item)
33
+ {
34
+ return build_stacking_rules_from_info(item.get_stacking_info(), item.get_json())
35
+ }
36
+
37
+ function is_maximum_stacking_enabled(json)
38
+ {
39
+ const stacking_unit = json.stackingUnit
40
+ return stacking_unit === 'maximumStacking' || stacking_unit === 'both'
41
+ }
42
+
43
+ function is_supported_weight_enabled(json)
44
+ {
45
+ const stacking_unit = json.stackingUnit
46
+ return stacking_unit === undefined || stacking_unit === 'supportedWeight' || stacking_unit === 'both'
47
+ }
48
+
49
+ module.exports = {
50
+ build_stacking_rules_from_info,
51
+ get_stacking_rules_input
52
+ }
@@ -0,0 +1,110 @@
1
+ const { Item_Amount_Controller } = require('@jetta/item-amount-controller')
2
+ const {
3
+ block_has_sufficient_shape_stock,
4
+ build_required_shape_amounts
5
+ } = require('./block_builder/block_shape_stock')
6
+ const { cube_map_function } = require('../Blocks_Preparation/Cube_Map_Function')
7
+
8
+ /**
9
+ * Trims chosen block instances using shape stock, simulating consumption in order.
10
+ *
11
+ * @param {{ block: object, amount: number }[]} chosen_blocks
12
+ * @param {object[]} item_list
13
+ * @returns {{ block: object, amount: number }[]}
14
+ */
15
+ function cap_chosen_blocks_by_shape_stock(chosen_blocks, item_list)
16
+ {
17
+ const item_map = build_item_map(item_list)
18
+ const provisional_amounts = new Item_Amount_Controller(item_list).copy()
19
+ const capped_choices = []
20
+
21
+ for (const choice of chosen_blocks)
22
+ {
23
+ const requested = Math.floor(Number(choice.amount) || 0)
24
+ if (requested <= 0 || choice.block.get_slot_list().length === 0)
25
+ {
26
+ continue
27
+ }
28
+ let allowed_instances = 0
29
+ for (let instance_index = 0; instance_index < requested; instance_index++)
30
+ {
31
+ if (!block_has_sufficient_shape_stock(choice.block, item_map, provisional_amounts))
32
+ {
33
+ break
34
+ }
35
+ deduct_block_from_amount_map(choice.block, item_map, provisional_amounts)
36
+ allowed_instances += 1
37
+ }
38
+ if (allowed_instances > 0)
39
+ {
40
+ capped_choices.push({ block: choice.block, amount: allowed_instances })
41
+ }
42
+ }
43
+
44
+ return capped_choices
45
+ }
46
+
47
+ /**
48
+ * @param {object[]} item_list
49
+ * @returns {object}
50
+ */
51
+ function build_item_map(item_list)
52
+ {
53
+ const item_map = {}
54
+ for (const item of item_list)
55
+ {
56
+ item_map[item.get_id()] = item
57
+ }
58
+ return item_map
59
+ }
60
+
61
+ /**
62
+ * @param {object} block
63
+ * @param {object} item_map
64
+ * @param {object} amount_map
65
+ * @returns {void}
66
+ */
67
+ function deduct_block_from_amount_map(block, item_map, amount_map)
68
+ {
69
+ const remaining_required = build_required_shape_amounts(block)
70
+ for (const [shape_hash, required_amount] of remaining_required)
71
+ {
72
+ let still_needed = required_amount
73
+ for (const item_id of Object.keys(item_map))
74
+ {
75
+ if (still_needed <= 0)
76
+ {
77
+ break
78
+ }
79
+ const item = item_map[item_id]
80
+ if (!item_can_form_shape(item, shape_hash))
81
+ {
82
+ continue
83
+ }
84
+ while (still_needed > 0 && amount_map.get_item_amount(item) > 0)
85
+ {
86
+ amount_map.discount_single_item(item)
87
+ still_needed -= 1
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * @param {object} item
95
+ * @param {string} shape_hash
96
+ * @returns {boolean}
97
+ */
98
+ function item_can_form_shape(item, shape_hash)
99
+ {
100
+ for (const rotated_item of item.get_all_rotated_options())
101
+ {
102
+ if (cube_map_function(rotated_item) === shape_hash)
103
+ {
104
+ return true
105
+ }
106
+ }
107
+ return false
108
+ }
109
+
110
+ module.exports = cap_chosen_blocks_by_shape_stock
@@ -0,0 +1,21 @@
1
+ const { get_weight_utilization, get_space_utilization } = require('./Container_Utilization')
2
+ const { select_adaptive_group_index } = require('./Adaptive_Density_Group_Selector')
3
+ const { get_groups_with_stock } = require('./Density_Group_Stock')
4
+
5
+ /**
6
+ * Computes the adaptive active group index from container utilization.
7
+ * @param {Map<number, Set<string>>} groups - Density group map.
8
+ * @param {number} group_count - Total group count.
9
+ * @param {number} active_group_index - Current active group index.
10
+ * @param {object} container - Current container.
11
+ * @param {object[]} item_list - Master item list.
12
+ * @returns {number}
13
+ */
14
+ function resolve_adaptive_group_index(groups, group_count, active_group_index, container, item_list)
15
+ {
16
+ const gap = get_weight_utilization(container) - get_space_utilization(container)
17
+ const stock_groups = get_groups_with_stock(groups, group_count, item_list)
18
+ return select_adaptive_group_index(gap, stock_groups, active_group_index)
19
+ }
20
+
21
+ module.exports = { resolve_adaptive_group_index }
@@ -0,0 +1,55 @@
1
+ const {
2
+ DEFAULT_WEIGHT_AHEAD_THRESHOLD,
3
+ DEFAULT_SPACE_AHEAD_THRESHOLD,
4
+ get_weight_ahead_threshold,
5
+ get_space_ahead_threshold,
6
+ } = require('./Adaptive_Density_Group_Threshold_Resolver')
7
+
8
+ const WEIGHT_AHEAD_THRESHOLD = DEFAULT_WEIGHT_AHEAD_THRESHOLD
9
+ const SPACE_AHEAD_THRESHOLD = DEFAULT_SPACE_AHEAD_THRESHOLD
10
+ const GAP_THRESHOLD = DEFAULT_SPACE_AHEAD_THRESHOLD
11
+
12
+ /**
13
+ * Picks the active density group from utilization gap and groups that still have stock.
14
+ * Weight-ahead and space-ahead thresholds are read from `Cargo_Profile` (defaults 10 pp / 15 pp).
15
+ * @param {number} gap - Weight utilization minus space utilization.
16
+ * @param {number[]} groups_with_stock - Group indices that still have items with amount > 0.
17
+ * @param {number} current_index - Current active group index.
18
+ * @returns {number} Selected group index.
19
+ */
20
+ function select_adaptive_group_index(gap, groups_with_stock, current_index)
21
+ {
22
+ if (groups_with_stock.length === 0)
23
+ {
24
+ return current_index
25
+ }
26
+
27
+ const lowest_density_group = Math.min(...groups_with_stock)
28
+ const highest_density_group = Math.max(...groups_with_stock)
29
+ const weight_ahead_threshold = get_weight_ahead_threshold()
30
+ const space_ahead_threshold = get_space_ahead_threshold()
31
+
32
+ if (gap > weight_ahead_threshold)
33
+ {
34
+ return lowest_density_group
35
+ }
36
+
37
+ if (gap < -space_ahead_threshold)
38
+ {
39
+ return highest_density_group
40
+ }
41
+
42
+ if (groups_with_stock.includes(current_index))
43
+ {
44
+ return current_index
45
+ }
46
+
47
+ return lowest_density_group
48
+ }
49
+
50
+ module.exports = {
51
+ WEIGHT_AHEAD_THRESHOLD,
52
+ SPACE_AHEAD_THRESHOLD,
53
+ GAP_THRESHOLD,
54
+ select_adaptive_group_index
55
+ }
@@ -0,0 +1,28 @@
1
+ const Cargo_Profile = require('../../models/Cargo_Profile')
2
+ const {
3
+ DEFAULT_WEIGHT_AHEAD_THRESHOLD,
4
+ DEFAULT_SPACE_AHEAD_THRESHOLD,
5
+ } = require('./Adaptive_Density_Group_Thresholds')
6
+
7
+ /**
8
+ * @returns {number} Weight-ahead gap threshold as a utilization fraction.
9
+ */
10
+ function get_weight_ahead_threshold()
11
+ {
12
+ return Cargo_Profile.density_groups_weight_ahead_threshold()
13
+ }
14
+
15
+ /**
16
+ * @returns {number} Space-ahead gap threshold as a utilization fraction.
17
+ */
18
+ function get_space_ahead_threshold()
19
+ {
20
+ return Cargo_Profile.density_groups_space_ahead_threshold()
21
+ }
22
+
23
+ module.exports = {
24
+ DEFAULT_WEIGHT_AHEAD_THRESHOLD,
25
+ DEFAULT_SPACE_AHEAD_THRESHOLD,
26
+ get_weight_ahead_threshold,
27
+ get_space_ahead_threshold,
28
+ }
@@ -0,0 +1,23 @@
1
+ const DEFAULT_WEIGHT_AHEAD_THRESHOLD_PP = 10
2
+ const DEFAULT_SPACE_AHEAD_THRESHOLD_PP = 15
3
+
4
+ const DEFAULT_WEIGHT_AHEAD_THRESHOLD = DEFAULT_WEIGHT_AHEAD_THRESHOLD_PP / 100
5
+ const DEFAULT_SPACE_AHEAD_THRESHOLD = DEFAULT_SPACE_AHEAD_THRESHOLD_PP / 100
6
+
7
+ /**
8
+ * Converts a percentage-point threshold to a utilization fraction.
9
+ * @param {number} percentage_points - Threshold in percentage points (e.g. 10 for 10 pp).
10
+ * @returns {number}
11
+ */
12
+ function percentage_points_to_fraction(percentage_points)
13
+ {
14
+ return percentage_points / 100
15
+ }
16
+
17
+ module.exports = {
18
+ DEFAULT_WEIGHT_AHEAD_THRESHOLD_PP,
19
+ DEFAULT_SPACE_AHEAD_THRESHOLD_PP,
20
+ DEFAULT_WEIGHT_AHEAD_THRESHOLD,
21
+ DEFAULT_SPACE_AHEAD_THRESHOLD,
22
+ percentage_points_to_fraction,
23
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Computes the fraction of supported weight already loaded in the container.
3
+ * @param {object} container - Container with supported_weight() and get_allocated_items().
4
+ * @returns {number} Value in [0, 1].
5
+ */
6
+ function get_weight_utilization(container)
7
+ {
8
+ const allocated_items = container.get_allocated_items()
9
+ if (allocated_items.length === 0)
10
+ {
11
+ return 0
12
+ }
13
+
14
+ const loaded_weight = allocated_items.reduce((sum, item) => sum + item.get_weight(), 0)
15
+ const remaining_weight = container.supported_weight()
16
+ const weight_limit = loaded_weight + remaining_weight
17
+
18
+ if (weight_limit <= 0)
19
+ {
20
+ return 0
21
+ }
22
+
23
+ return loaded_weight / weight_limit
24
+ }
25
+
26
+ /**
27
+ * Computes the fraction of container volume occupied by allocated items.
28
+ * @param {object} container - Container with dimensions and get_allocated_items().
29
+ * @returns {number} Value in [0, 1].
30
+ */
31
+ function get_space_utilization(container)
32
+ {
33
+ const total_volume = get_container_volume(container)
34
+ if (total_volume <= 0)
35
+ {
36
+ return 0
37
+ }
38
+
39
+ const loaded_volume = sum_allocated_volume(container)
40
+ return Math.min(1, loaded_volume / total_volume)
41
+ }
42
+
43
+ /**
44
+ * @param {object} container - Container with get_allocated_items().
45
+ * @returns {number}
46
+ */
47
+ function sum_allocated_volume(container)
48
+ {
49
+ return container.get_allocated_items().reduce((sum, item) =>
50
+ {
51
+ return sum + item.get_width() * item.get_height() * item.get_length()
52
+ }, 0)
53
+ }
54
+
55
+ /**
56
+ * @param {object} container - Container with width, height, length accessors.
57
+ * @returns {number}
58
+ */
59
+ function get_container_volume(container)
60
+ {
61
+ return container.get_width() * container.get_height() * container.get_length()
62
+ }
63
+
64
+ module.exports = {
65
+ get_weight_utilization,
66
+ get_space_utilization
67
+ }
@@ -0,0 +1,74 @@
1
+ const { calculate_item_density } = require('./Item_Density_Calculator')
2
+
3
+ /**
4
+ * Partitions SKUs into density quantile groups (low to high density).
5
+ * @param {object[]} item_list - Items with get_id and dimensions.
6
+ * @param {number} group_count - Number of groups (>= 2).
7
+ * @returns {{ groups: Map<number, Set<string>>, group_meta: Array<{ index: number, min_density: number, max_density: number, size: number }> }}
8
+ */
9
+ function partition_items_by_density(item_list, group_count)
10
+ {
11
+ const count = Math.max(2, group_count)
12
+ const entries = item_list.map(calculate_item_density)
13
+
14
+ entries.sort((left, right) =>
15
+ {
16
+ if (left.density !== right.density)
17
+ {
18
+ return left.density - right.density
19
+ }
20
+ return String(left.item_id).localeCompare(String(right.item_id))
21
+ })
22
+
23
+ const groups = new Map()
24
+ const group_meta = []
25
+ const total = entries.length
26
+
27
+ for (let group_index = 0; group_index < count; group_index++)
28
+ {
29
+ groups.set(group_index, new Set())
30
+ }
31
+
32
+ if (total === 0)
33
+ {
34
+ return { groups, group_meta }
35
+ }
36
+
37
+ let cursor = 0
38
+ for (let group_index = 0; group_index < count; group_index++)
39
+ {
40
+ const remaining_groups = count - group_index
41
+ const remaining_items = total - cursor
42
+ const bucket_size = Math.ceil(remaining_items / remaining_groups)
43
+ const bucket = entries.slice(cursor, cursor + bucket_size)
44
+ cursor += bucket_size
45
+
46
+ const id_set = groups.get(group_index)
47
+ let min_density = Number.POSITIVE_INFINITY
48
+ let max_density = Number.NEGATIVE_INFINITY
49
+
50
+ for (const entry of bucket)
51
+ {
52
+ id_set.add(entry.item_id)
53
+ min_density = Math.min(min_density, entry.density)
54
+ max_density = Math.max(max_density, entry.density)
55
+ }
56
+
57
+ if (bucket.length === 0)
58
+ {
59
+ min_density = 0
60
+ max_density = 0
61
+ }
62
+
63
+ group_meta.push({
64
+ index: group_index,
65
+ min_density,
66
+ max_density,
67
+ size: bucket.length
68
+ })
69
+ }
70
+
71
+ return { groups, group_meta }
72
+ }
73
+
74
+ module.exports = { partition_items_by_density }
@@ -0,0 +1,168 @@
1
+ const Cargo_Profile = require('../../models/Cargo_Profile')
2
+ const { DENSITY_GROUPS_STRATEGY } = require('./Density_Groups_Strategy')
3
+ const { partition_items_by_density } = require('./Density_Group_Partitioner')
4
+ const { resolve_adaptive_group_index } = require('./Adaptive_Density_Group_Preparer')
5
+ const {
6
+ find_group_index_for_item_id: find_item_group_index,
7
+ get_groups_with_stock: resolve_groups_with_stock
8
+ } = require('./Density_Group_Stock')
9
+
10
+ class Density_Group_Scheduler
11
+ {
12
+ #groups
13
+ #group_count
14
+ #active_group_index = 0
15
+
16
+ /**
17
+ * @param {object[]} item_list - Full master item list at flow start.
18
+ */
19
+ constructor(item_list)
20
+ {
21
+ this.#group_count = Cargo_Profile.density_groups_count()
22
+ const { groups } = partition_items_by_density(item_list, this.#group_count)
23
+ this.#groups = groups
24
+ }
25
+
26
+ /**
27
+ * @param {object[]} item_list - Candidate items (may already be lock-filtered).
28
+ * @returns {object[]} Items in the active density group with stock > 0.
29
+ */
30
+ filter_item_list(item_list)
31
+ {
32
+ const active_ids = this.#groups.get(this.#active_group_index)
33
+ if (!active_ids)
34
+ {
35
+ return []
36
+ }
37
+
38
+ return item_list.filter(item => active_ids.has(item.get_id()) && item.get_amount() > 0)
39
+ }
40
+
41
+ /**
42
+ * @returns {boolean} True when the active group has at least one item with stock.
43
+ */
44
+ active_group_has_stock(item_list)
45
+ {
46
+ return this.filter_item_list(item_list).length > 0
47
+ }
48
+
49
+ /**
50
+ * Advances to the next non-empty group. Returns false when no group has stock.
51
+ * @param {object[]} item_list - Master item list.
52
+ * @returns {boolean}
53
+ */
54
+ skip_empty_groups(item_list)
55
+ {
56
+ if (this.#group_count <= 0)
57
+ {
58
+ return false
59
+ }
60
+
61
+ for (let step = 0; step < this.#group_count; step++)
62
+ {
63
+ if (this.active_group_has_stock(item_list))
64
+ {
65
+ return true
66
+ }
67
+ this.#active_group_index = (this.#active_group_index + 1) % this.#group_count
68
+ }
69
+
70
+ return false
71
+ }
72
+
73
+ /**
74
+ * Sets the active group before an iteration when adaptive strategy is enabled.
75
+ * @param {object} container - Current container.
76
+ * @param {object[]} item_list - Master item list.
77
+ * @param {object|null} locked_item - Item continuation lock, if any.
78
+ * @returns {void}
79
+ */
80
+ prepare_for_iteration(container, item_list, locked_item)
81
+ {
82
+ if (locked_item || Cargo_Profile.density_groups_strategy() !== DENSITY_GROUPS_STRATEGY.ADAPTIVE)
83
+ {
84
+ return
85
+ }
86
+
87
+ this.#active_group_index = resolve_adaptive_group_index(
88
+ this.#groups,
89
+ this.#group_count,
90
+ this.#active_group_index,
91
+ container,
92
+ item_list
93
+ )
94
+ }
95
+
96
+ /**
97
+ * Round-robin: move to the next density group after a successful wall allocation.
98
+ * @returns {void}
99
+ */
100
+ advance_after_successful_wall()
101
+ {
102
+ this.#active_group_index = (this.#active_group_index + 1) % this.#group_count
103
+ }
104
+
105
+ /**
106
+ * Notifies the scheduler after a successful wall based on the configured strategy.
107
+ * @returns {void}
108
+ */
109
+ on_successful_wall()
110
+ {
111
+ if (Cargo_Profile.density_groups_strategy() === DENSITY_GROUPS_STRATEGY.ADAPTIVE)
112
+ {
113
+ return
114
+ }
115
+
116
+ this.advance_after_successful_wall()
117
+ }
118
+
119
+ /**
120
+ * @returns {number}
121
+ */
122
+ get_active_group_index()
123
+ {
124
+ return this.#active_group_index
125
+ }
126
+
127
+ /**
128
+ * @returns {number}
129
+ */
130
+ get_group_count()
131
+ {
132
+ return this.#group_count
133
+ }
134
+
135
+ /**
136
+ * @param {string} item_id - Item identifier.
137
+ * @returns {number|null}
138
+ */
139
+ find_group_index_for_item_id(item_id)
140
+ {
141
+ return find_item_group_index(this.#groups, this.#group_count, item_id)
142
+ }
143
+
144
+ /**
145
+ * @param {object[]} item_list - Master item list.
146
+ * @returns {number[]}
147
+ */
148
+ get_groups_with_stock(item_list)
149
+ {
150
+ return resolve_groups_with_stock(this.#groups, this.#group_count, item_list)
151
+ }
152
+ }
153
+
154
+ /**
155
+ * @param {object[]} item_list - Master item list.
156
+ * @returns {Density_Group_Scheduler|null}
157
+ */
158
+ function create_density_group_scheduler(item_list)
159
+ {
160
+ if (!Cargo_Profile.enable_density_groups())
161
+ {
162
+ return null
163
+ }
164
+
165
+ return new Density_Group_Scheduler(item_list)
166
+ }
167
+
168
+ module.exports = { Density_Group_Scheduler, create_density_group_scheduler }