@jetta/blocks-allocator 0.0.0-stage → 0.1.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,119 @@
1
+ const math = require('@jetta/number-compare')
2
+ const { supporters_at_top_y } = require('../supporters_by_top_y_index')
3
+ const { is_tie_ratio_supporter } = require('./tie_ratio_supporter_predicate')
4
+ const { footprint_overlap_score } = require('./tie_ratio_footprint_overlap')
5
+ const compare_group_ids = require('./compare_group_ids')
6
+
7
+ function group_supporters_by_group_id(supporter_list)
8
+ {
9
+ const groups = new Map()
10
+ for (const item of supporter_list)
11
+ {
12
+ if (!is_tie_ratio_supporter(item))
13
+ {
14
+ continue
15
+ }
16
+ const group_id = item.get_group_id()
17
+ if (!groups.has(group_id))
18
+ {
19
+ groups.set(group_id, [])
20
+ }
21
+ groups.get(group_id).push(item)
22
+ }
23
+ return groups
24
+ }
25
+
26
+ /**
27
+ * @param {object} item
28
+ * @param {number} space_bottom
29
+ * @returns {boolean}
30
+ */
31
+ function is_supporter_at_placement_plane(item, space_bottom)
32
+ {
33
+ return math.eq(item.get_y() + item.get_height(), space_bottom)
34
+ }
35
+
36
+ /**
37
+ * @param {object} container
38
+ * @param {import('../supporters_by_top_y_index').Supporters_By_Top_Y_Index|undefined} supporters_by_top_y_index
39
+ * @param {number} space_bottom
40
+ * @param {object} empty_space
41
+ * @param {object|undefined} placement_options
42
+ * @returns {object[]}
43
+ */
44
+ function resolve_supporters(
45
+ container,
46
+ supporters_by_top_y_index,
47
+ space_bottom,
48
+ empty_space,
49
+ placement_options
50
+ )
51
+ {
52
+ if (supporters_by_top_y_index !== undefined)
53
+ {
54
+ return supporters_at_top_y(supporters_by_top_y_index, space_bottom)
55
+ }
56
+ return (container.get_allocated_items?.() ?? []).filter(item =>
57
+ is_tie_ratio_supporter(item)
58
+ && is_supporter_at_placement_plane(item, space_bottom)
59
+ && footprint_overlap_score(item, empty_space, placement_options) > 0
60
+ )
61
+ }
62
+
63
+ /**
64
+ * @param {number} score
65
+ * @param {number} best_score
66
+ * @param {string|number} group_id
67
+ * @param {{ group_id: string|number }|undefined} best_cluster
68
+ * @returns {boolean}
69
+ */
70
+ function should_replace_best_cluster(score, best_score, group_id, best_cluster)
71
+ {
72
+ if (math.eq(score, best_score) && best_cluster !== undefined)
73
+ {
74
+ return compare_group_ids(group_id, best_cluster.group_id) < 0
75
+ }
76
+ return score > best_score
77
+ }
78
+
79
+ /**
80
+ * @param {object[]} supporter_list
81
+ * @param {object} empty_space
82
+ * @param {object|undefined} placement_options
83
+ * @returns {{ group_id: string|number, orientation: string, items: object[] }|undefined}
84
+ */
85
+ function select_best_cluster(supporter_list, empty_space, placement_options)
86
+ {
87
+ const groups = group_supporters_by_group_id(supporter_list)
88
+ let best_cluster = undefined
89
+ let best_score = -1
90
+
91
+ for (const [group_id, items] of groups.entries())
92
+ {
93
+ if (items.length < 2)
94
+ {
95
+ continue
96
+ }
97
+ const score = items.reduce(
98
+ (total, item) => total + footprint_overlap_score(item, empty_space, placement_options),
99
+ 0
100
+ )
101
+ if (!should_replace_best_cluster(score, best_score, group_id, best_cluster))
102
+ {
103
+ continue
104
+ }
105
+ best_score = score
106
+ best_cluster = {
107
+ group_id,
108
+ orientation: items[0].get_tie_ratio_orientation(),
109
+ items
110
+ }
111
+ }
112
+
113
+ return best_score > 0 ? best_cluster : undefined
114
+ }
115
+
116
+ module.exports = {
117
+ resolve_supporters,
118
+ select_best_cluster
119
+ }
@@ -0,0 +1,56 @@
1
+ const axis_overlap_length = require('./axis_overlap_length')
2
+
3
+ /**
4
+ * @param {object} item
5
+ * @param {object} region
6
+ * @returns {number}
7
+ */
8
+ function footprint_overlap_on_space(item, region)
9
+ {
10
+ const x_overlap = axis_overlap_length(
11
+ item.get_x(),
12
+ item.get_x() + item.get_width(),
13
+ region.get_x(),
14
+ region.get_x() + region.get_width()
15
+ )
16
+ const z_overlap = axis_overlap_length(
17
+ item.get_z(),
18
+ item.get_z() + item.get_length(),
19
+ region.get_z(),
20
+ region.get_z() + region.get_length()
21
+ )
22
+ return x_overlap * z_overlap
23
+ }
24
+
25
+ /**
26
+ * @param {object} item
27
+ * @param {object} empty_space
28
+ * @param {{ loose_origin_x?: number, loose_origin_z?: number, item_width?: number, item_length?: number }|undefined} placement_options
29
+ * @returns {number}
30
+ */
31
+ function footprint_overlap_score(item, empty_space, placement_options)
32
+ {
33
+ const empty_score = footprint_overlap_on_space(item, empty_space)
34
+ if (empty_score > 0)
35
+ {
36
+ return empty_score
37
+ }
38
+ if (placement_options?.loose_origin_x === undefined
39
+ || placement_options?.loose_origin_z === undefined
40
+ || placement_options?.item_width === undefined
41
+ || placement_options?.item_length === undefined)
42
+ {
43
+ return 0
44
+ }
45
+ return footprint_overlap_on_space(item, {
46
+ get_x: () => placement_options.loose_origin_x,
47
+ get_z: () => placement_options.loose_origin_z,
48
+ get_width: () => placement_options.item_width,
49
+ get_length: () => placement_options.item_length
50
+ })
51
+ }
52
+
53
+ module.exports = {
54
+ footprint_overlap_on_space,
55
+ footprint_overlap_score
56
+ }
@@ -0,0 +1,109 @@
1
+ const math = require('@jetta/number-compare')
2
+ const { is_tie_ratio_supporter } = require('./tie_ratio_supporter_predicate')
3
+ const { footprint_overlap_score } = require('./tie_ratio_footprint_overlap')
4
+
5
+ function list_overlapping_tie_supporters(
6
+ container,
7
+ supporters_by_top_y_index,
8
+ empty_space,
9
+ placement_options
10
+ )
11
+ {
12
+ const overlaps = (item) => footprint_overlap_score(item, empty_space, placement_options) > 0
13
+ if (supporters_by_top_y_index !== undefined)
14
+ {
15
+ const merged = []
16
+ for (const bucket of supporters_by_top_y_index.bucket_list)
17
+ {
18
+ merged.push(...bucket.items)
19
+ }
20
+ return merged.filter(item => is_tie_ratio_supporter(item) && overlaps(item))
21
+ }
22
+ return (container.get_allocated_items?.() ?? []).filter(item =>
23
+ is_tie_ratio_supporter(item) && overlaps(item)
24
+ )
25
+ }
26
+
27
+ /**
28
+ * @param {object} container
29
+ * @param {import('../supporters_by_top_y_index').Supporters_By_Top_Y_Index|undefined} supporters_by_top_y_index
30
+ * @param {object} empty_space
31
+ * @param {object|undefined} placement_options
32
+ * @returns {number[]}
33
+ */
34
+ function distinct_supporter_tops_overlapping(
35
+ container,
36
+ supporters_by_top_y_index,
37
+ empty_space,
38
+ placement_options
39
+ )
40
+ {
41
+ const supporters = list_overlapping_tie_supporters(
42
+ container,
43
+ supporters_by_top_y_index,
44
+ empty_space,
45
+ placement_options
46
+ )
47
+ const tops = supporters.map(item => item.get_y() + item.get_height())
48
+ return [...new Set(tops)].sort((left, right) => left - right)
49
+ }
50
+
51
+ /**
52
+ * @param {object} container
53
+ * @param {object} empty_space
54
+ * @param {import('../supporters_by_top_y_index').Supporters_By_Top_Y_Index|undefined} supporters_by_top_y_index
55
+ * @param {number|undefined} placement_bottom_y
56
+ * @param {object|undefined} placement_options
57
+ * @returns {number|undefined}
58
+ */
59
+ function resolve_placement_plane(
60
+ container,
61
+ empty_space,
62
+ supporters_by_top_y_index,
63
+ placement_bottom_y,
64
+ placement_options
65
+ )
66
+ {
67
+ const empty_bottom = empty_space.get_y()
68
+ if (math.gt(empty_bottom, 0))
69
+ {
70
+ return empty_bottom
71
+ }
72
+
73
+ const candidate_tops = distinct_supporter_tops_overlapping(
74
+ container,
75
+ supporters_by_top_y_index,
76
+ empty_space,
77
+ placement_options
78
+ )
79
+ if (candidate_tops.length === 0)
80
+ {
81
+ return placement_bottom_y
82
+ }
83
+
84
+ if (placement_bottom_y !== undefined && math.gt(placement_bottom_y, 0))
85
+ {
86
+ const exact_top = candidate_tops.find(top => math.eq(top, placement_bottom_y))
87
+ if (exact_top !== undefined)
88
+ {
89
+ return exact_top
90
+ }
91
+
92
+ const item_height = placement_options?.item_height ?? 0
93
+ const loose_top = placement_bottom_y + item_height
94
+ const supporting_tops = candidate_tops.filter(top =>
95
+ math.le(top, loose_top)
96
+ )
97
+ if (supporting_tops.length > 0)
98
+ {
99
+ return supporting_tops[supporting_tops.length - 1]
100
+ }
101
+ }
102
+
103
+ return candidate_tops[candidate_tops.length - 1]
104
+ }
105
+
106
+ module.exports = {
107
+ resolve_placement_plane,
108
+ list_overlapping_tie_supporters
109
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @param {string|number|undefined|null} group_id
3
+ * @returns {boolean}
4
+ */
5
+ function has_group_id(group_id)
6
+ {
7
+ return group_id !== undefined && group_id !== null
8
+ }
9
+
10
+ /**
11
+ * @param {object} item
12
+ * @returns {boolean}
13
+ */
14
+ function is_tie_ratio_supporter(item)
15
+ {
16
+ const orientation = item.get_tie_ratio_orientation?.()
17
+ return has_group_id(item.get_group_id()) && (orientation === '3_2' || orientation === '2_3')
18
+ }
19
+
20
+ module.exports = {
21
+ has_group_id,
22
+ is_tie_ratio_supporter
23
+ }
@@ -0,0 +1,62 @@
1
+ const find_next_free_slot_index = require('./find_next_free_slot_index')
2
+ const {
3
+ mark_slot_occupied,
4
+ register_pending_footprint
5
+ } = require('./loose_on_block_slot_state')
6
+
7
+ /**
8
+ * @param {object} container
9
+ * @param {object} slot
10
+ * @param {number} placement_y
11
+ * @param {object} slot_state
12
+ * @param {{ group_id: string|number, items: object[] }} cluster
13
+ * @param {object|undefined} placement_options
14
+ * @returns {{ x: number, y: number, z: number, slot_index: number, group_id: string|number }|undefined}
15
+ */
16
+ function try_tie_ratio_slot_placement(
17
+ container,
18
+ slot,
19
+ placement_y,
20
+ slot_state,
21
+ cluster,
22
+ placement_options
23
+ )
24
+ {
25
+ if (find_next_free_slot_index(
26
+ container,
27
+ [slot],
28
+ placement_y,
29
+ slot_state,
30
+ cluster.group_id,
31
+ placement_options
32
+ ) === undefined)
33
+ {
34
+ return undefined
35
+ }
36
+
37
+ const placement = {
38
+ x: slot.x,
39
+ y: placement_y,
40
+ z: slot.z,
41
+ slot_index: slot.index,
42
+ group_id: cluster.group_id
43
+ }
44
+ mark_slot_occupied(slot_state, cluster.group_id, placement_y, slot.index)
45
+ if (placement_options?.item_width !== undefined
46
+ && placement_options?.item_length !== undefined
47
+ && placement_options?.item_height !== undefined)
48
+ {
49
+ register_pending_footprint(
50
+ slot_state,
51
+ placement_y,
52
+ placement.x,
53
+ placement.z,
54
+ placement_options.item_width,
55
+ placement_options.item_length,
56
+ placement_options.item_height
57
+ )
58
+ }
59
+ return placement
60
+ }
61
+
62
+ module.exports = try_tie_ratio_slot_placement
@@ -0,0 +1,138 @@
1
+ const math = require('@jetta/number-compare')
2
+ const No_Suitable_Item_Exception = require('../block_builder/exceptions/No_Suitable_Item_Exception')
3
+ const { ALLOCATOR_MESSAGE } = require('../../messages/Allocator_Message')
4
+
5
+ const FLOOR_Y = 0
6
+
7
+ /**
8
+ * Copies floor (x, z) onto stacked items so each sits on a unique compatible footprint.
9
+ * @param {object[]} stacked_items
10
+ * @param {object[]} allocated_items
11
+ * @returns {object[]}
12
+ */
13
+ function snap_stacked_items_to_floor_footprints(stacked_items, allocated_items)
14
+ {
15
+ if (!layer_is_elevated(stacked_items))
16
+ {
17
+ return stacked_items
18
+ }
19
+ const remaining_floor = collect_overlapping_floor_items(stacked_items, allocated_items)
20
+ return stacked_items.map(stacked => take_floor_twin(stacked, remaining_floor, allocated_items))
21
+ }
22
+
23
+ function layer_is_elevated(items)
24
+ {
25
+ return items.some(item => math.gt(item.get_y(), FLOOR_Y))
26
+ }
27
+
28
+ function collect_overlapping_floor_items(stacked_items, allocated_items)
29
+ {
30
+ const aabb = cluster_xz_aabb(stacked_items)
31
+ return allocated_items.filter(item => math.eq(item.get_y(), FLOOR_Y) && xz_overlaps_aabb(item, aabb))
32
+ }
33
+
34
+ function take_floor_twin(stacked, remaining_floor, allocated_items)
35
+ {
36
+ const index = find_free_floor_twin_index(stacked, remaining_floor, allocated_items)
37
+ if (index < 0)
38
+ {
39
+ throw new No_Suitable_Item_Exception(ALLOCATOR_MESSAGE.NO_FLOOR_FOOTPRINT_TWIN)
40
+ }
41
+ const [floor] = remaining_floor.splice(index, 1)
42
+ return copy_xz(stacked, floor)
43
+ }
44
+
45
+ function find_free_floor_twin_index(stacked, remaining_floor, allocated_items)
46
+ {
47
+ let best_index = -1
48
+ let best_distance = Infinity
49
+ for (let index = 0; index < remaining_floor.length; index++)
50
+ {
51
+ const floor = remaining_floor[index]
52
+ if (!is_free_matching_floor(stacked, floor, allocated_items))
53
+ {
54
+ continue
55
+ }
56
+ const distance = xz_distance_squared(stacked, floor)
57
+ if (distance < best_distance)
58
+ {
59
+ best_distance = distance
60
+ best_index = index
61
+ }
62
+ }
63
+ return best_index
64
+ }
65
+
66
+ function is_free_matching_floor(stacked, floor, allocated_items)
67
+ {
68
+ return footprints_match(stacked, floor) && !floor_has_elevated_occupant(floor, stacked, allocated_items)
69
+ }
70
+
71
+ function xz_distance_squared(stacked, floor)
72
+ {
73
+ const dx = stacked.get_x() - floor.get_x()
74
+ const dz = stacked.get_z() - floor.get_z()
75
+ return dx * dx + dz * dz
76
+ }
77
+
78
+ function floor_has_elevated_occupant(floor, stacked, allocated_items)
79
+ {
80
+ const destination = {
81
+ get_x: () => floor.get_x(),
82
+ get_y: () => stacked.get_y(),
83
+ get_z: () => floor.get_z(),
84
+ get_width: () => stacked.get_width(),
85
+ get_height: () => stacked.get_height(),
86
+ get_length: () => stacked.get_length()
87
+ }
88
+ return allocated_items.some(item => elevated_item_overlaps(item, destination))
89
+ }
90
+
91
+ function elevated_item_overlaps(item, destination)
92
+ {
93
+ return math.gt(item.get_y(), FLOOR_Y) && items_overlap_volume(item, destination)
94
+ }
95
+
96
+ function items_overlap_volume(item_a, item_b)
97
+ {
98
+ const overlap_x = Math.min(item_a.get_x() + item_a.get_width(), item_b.get_x() + item_b.get_width())
99
+ - Math.max(item_a.get_x(), item_b.get_x())
100
+ const overlap_y = Math.min(item_a.get_y() + item_a.get_height(), item_b.get_y() + item_b.get_height())
101
+ - Math.max(item_a.get_y(), item_b.get_y())
102
+ const overlap_z = Math.min(item_a.get_z() + item_a.get_length(), item_b.get_z() + item_b.get_length())
103
+ - Math.max(item_a.get_z(), item_b.get_z())
104
+ return overlap_x > 1e-6 && overlap_y > 1e-6 && overlap_z > 1e-6
105
+ }
106
+
107
+ function footprints_match(stacked, floor)
108
+ {
109
+ return math.eq(stacked.get_width(), floor.get_width())
110
+ && math.eq(stacked.get_length(), floor.get_length())
111
+ }
112
+
113
+ function copy_xz(stacked, floor)
114
+ {
115
+ stacked.x = floor.get_x()
116
+ stacked.z = floor.get_z()
117
+ return stacked
118
+ }
119
+
120
+ function cluster_xz_aabb(items)
121
+ {
122
+ return {
123
+ min_x: Math.min(...items.map(item => item.get_x())),
124
+ max_x: Math.max(...items.map(item => item.get_x() + item.get_width())),
125
+ min_z: Math.min(...items.map(item => item.get_z())),
126
+ max_z: Math.max(...items.map(item => item.get_z() + item.get_length()))
127
+ }
128
+ }
129
+
130
+ function xz_overlaps_aabb(item, aabb)
131
+ {
132
+ const max_x = item.get_x() + item.get_width()
133
+ const max_z = item.get_z() + item.get_length()
134
+ return item.get_x() < aabb.max_x && aabb.min_x < max_x
135
+ && item.get_z() < aabb.max_z && aabb.min_z < max_z
136
+ }
137
+
138
+ module.exports = snap_stacked_items_to_floor_footprints
@@ -0,0 +1,78 @@
1
+ const math = require('@jetta/number-compare')
2
+
3
+ /**
4
+ * @typedef {object} Supporters_By_Top_Y_Index
5
+ * @property {Array<{ top_y: number, items: object[] }>} bucket_list
6
+ */
7
+
8
+ /**
9
+ * Groups allocated items by top Y for fast supporter lookup.
10
+ * Buckets stay sorted by top_y; float-equal levels merge via math.eq.
11
+ * @param {object[]} allocated_items
12
+ * @returns {Supporters_By_Top_Y_Index}
13
+ */
14
+ function build_supporters_by_top_y_index(allocated_items)
15
+ {
16
+ const bucket_list = []
17
+ for (const item of allocated_items)
18
+ {
19
+ const top_y = item.get_y() + item.get_height()
20
+ const slot = bucket_slot_for_top_y(bucket_list, top_y)
21
+ if (slot >= 0)
22
+ {
23
+ bucket_list[slot].items.push(item)
24
+ continue
25
+ }
26
+ bucket_list.splice(~slot, 0, { top_y, items: [item] })
27
+ }
28
+ return { bucket_list }
29
+ }
30
+
31
+ /**
32
+ * Returns allocated items whose top Y equals the requested level.
33
+ * @param {Supporters_By_Top_Y_Index} index
34
+ * @param {number} top_y
35
+ * @returns {object[]}
36
+ */
37
+ function supporters_at_top_y(index, top_y)
38
+ {
39
+ const slot = bucket_slot_for_top_y(index.bucket_list, top_y)
40
+ if (slot < 0)
41
+ {
42
+ return []
43
+ }
44
+ return index.bucket_list[slot].items
45
+ }
46
+
47
+ /**
48
+ * Lower-bound binary search for a bucket by top_y (math.eq for matches).
49
+ * @param {Array<{ top_y: number, items: object[] }>} bucket_list
50
+ * @param {number} top_y
51
+ * @returns {number} Found index (>= 0), or ~insertion_index when absent
52
+ */
53
+ function bucket_slot_for_top_y(bucket_list, top_y)
54
+ {
55
+ let low = 0
56
+ let high = bucket_list.length
57
+ while (low < high)
58
+ {
59
+ const mid = (low + high) >> 1
60
+ const mid_top_y = bucket_list[mid].top_y
61
+ if (math.eq(mid_top_y, top_y))
62
+ {
63
+ return mid
64
+ }
65
+ if (mid_top_y < top_y)
66
+ {
67
+ low = mid + 1
68
+ continue
69
+ }
70
+ high = mid
71
+ }
72
+ return ~low
73
+ }
74
+
75
+ module.exports = {
76
+ build_supporters_by_top_y_index,
77
+ supporters_at_top_y
78
+ }
@@ -0,0 +1,89 @@
1
+ const find_orientation_below_space = require('./find_orientation_below_space')
2
+ const { build_supporters_by_top_y_index } = require('./supporters_by_top_y_index')
3
+ const { collect_tie_ratio_orientations_below_footprint } = require('./collect_tie_ratio_orientations_below_footprint')
4
+
5
+ /**
6
+ * Resolves tie-ratio orientation of the compound supporter under an empty space footprint.
7
+ * @param {object} filter_like
8
+ * @param {object} filter_like.container
9
+ * @param {object|undefined} filter_like.empty_space
10
+ * @param {import('./supporters_by_top_y_index').Supporters_By_Top_Y_Index|undefined} [filter_like.supporters_by_top_y_index]
11
+ * @returns {'3_2'|'2_3'|undefined}
12
+ */
13
+ function tie_ratio_orientation_below_empty_space(filter_like)
14
+ {
15
+ const orientations = tie_ratio_orientations_below_empty_space(filter_like)
16
+ if (orientations.length !== 1)
17
+ {
18
+ return undefined
19
+ }
20
+ return orientations[0]
21
+ }
22
+
23
+ /**
24
+ * @param {object} filter_like
25
+ * @returns {Array<'3_2'|'2_3'>}
26
+ */
27
+ function tie_ratio_orientations_below_empty_space(filter_like)
28
+ {
29
+ const empty_space = filter_like.empty_space
30
+ if (empty_space === undefined || empty_space.get_y() <= 0)
31
+ {
32
+ return []
33
+ }
34
+
35
+ const container = filter_like.container
36
+ const allocated_items = container.get_allocated_items?.() ?? []
37
+ const supporters_by_top_y_index = filter_like.supporters_by_top_y_index
38
+ ?? build_supporters_by_top_y_index(allocated_items)
39
+
40
+ return collect_tie_ratio_orientations_below_footprint(
41
+ container,
42
+ empty_space,
43
+ supporters_by_top_y_index
44
+ )
45
+ }
46
+
47
+ /**
48
+ * @param {object} filter_like
49
+ * @returns {boolean}
50
+ */
51
+ function empty_space_stacks_on_tie_ratio_supporter(filter_like)
52
+ {
53
+ return tie_ratio_orientations_below_empty_space(filter_like).length > 0
54
+ }
55
+
56
+ /**
57
+ * @param {object} container
58
+ * @param {{ x: number, y: number, z: number }} placement_origin
59
+ * @param {number} block_width
60
+ * @param {number} block_length
61
+ * @param {import('./supporters_by_top_y_index').Supporters_By_Top_Y_Index|undefined} [supporters_by_top_y_index]
62
+ * @returns {'3_2'|'2_3'|undefined}
63
+ */
64
+ function tie_ratio_orientation_below_placement(
65
+ container,
66
+ placement_origin,
67
+ block_width,
68
+ block_length,
69
+ supporters_by_top_y_index
70
+ )
71
+ {
72
+ const footprint_space = {
73
+ get_y: () => placement_origin.y,
74
+ get_x: () => placement_origin.x,
75
+ get_z: () => placement_origin.z,
76
+ get_width: () => block_width,
77
+ get_length: () => block_length
78
+ }
79
+ return find_orientation_below_space(
80
+ container,
81
+ footprint_space,
82
+ supporters_by_top_y_index
83
+ )
84
+ }
85
+
86
+ module.exports = tie_ratio_orientation_below_empty_space
87
+ module.exports.tie_ratio_orientations_below_empty_space = tie_ratio_orientations_below_empty_space
88
+ module.exports.empty_space_stacks_on_tie_ratio_supporter = empty_space_stacks_on_tie_ratio_supporter
89
+ module.exports.tie_ratio_orientation_below_placement = tie_ratio_orientation_below_placement