@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,47 @@
1
+ const get_list_of_items_to_allocate = require('./item_preparation/Items_Reader')
2
+ const create_blocks = require('./block_preparation/Blocks_Creator')
3
+ const calculate_block_slots_stackability_index = require('./stackability_index/Blocks_Stackability_Index_Calculator')
4
+ const format_block_list = require('./Block_Formatter')
5
+ const create_transport = require('../models/transport/factory/Transport_Factory')
6
+ const build_empty_space_finder_options = require('./build_empty_space_finder_options')
7
+
8
+ /**
9
+ * Assembles the object consumed by `Allocation_flow`: transport, items, and prepared blocks.
10
+ * @param {object} input_data - Full allocation request (e.g. `envs`, `items`, `available_blocks`).
11
+ * @param {{ get_object: Function }} [object_store]
12
+ * @returns {Promise<object>} `input_state` with `transport`, `items_to_allocate`, and `blocks`.
13
+ */
14
+ async function build_input_state(input_data, object_store)
15
+ {
16
+ const item_list = get_list_of_items_to_allocate(input_data.items)
17
+ const empty_space_finder_options = build_empty_space_finder_options(
18
+ input_data.config,
19
+ item_list
20
+ )
21
+ const transport = create_transport({
22
+ transport_data: input_data.envs[0],
23
+ empty_space_finder_options,
24
+ item_list
25
+ })
26
+ const blocks = await get_blocks(
27
+ input_data.available_blocks,
28
+ input_data.envs[0],
29
+ item_list,
30
+ object_store
31
+ )
32
+ return {
33
+ items_to_allocate: item_list,
34
+ transport,
35
+ blocks
36
+ }
37
+ }
38
+
39
+ async function get_blocks(block_path_list, transport, item_list, object_store)
40
+ {
41
+ const filtered_blocks = await create_blocks(block_path_list, transport, item_list, object_store)
42
+ const formatted_block_list = format_block_list(filtered_blocks)
43
+ calculate_block_slots_stackability_index(formatted_block_list, item_list)
44
+ return formatted_block_list
45
+ }
46
+
47
+ module.exports = build_input_state
@@ -0,0 +1,27 @@
1
+ const Cargo_Profile = require('../models/Cargo_Profile')
2
+ const create_input_state = require('./Input_State_Preparation')
3
+
4
+ /**
5
+ * Hydrates cargo profile and builds the allocation input state.
6
+ * @param {object} input_data
7
+ * @param {{ object_store?: { get_object: Function } }} [dependencies]
8
+ * @returns {Promise<object>}
9
+ */
10
+ async function build_state(input_data, dependencies = {})
11
+ {
12
+ build_config_state(input_data)
13
+ const input_state = await create_input_state(input_data, dependencies.object_store)
14
+ return input_state
15
+ }
16
+
17
+ module.exports = build_state
18
+
19
+ function build_config_state(input_data)
20
+ {
21
+ Cargo_Profile.reset()
22
+ const cargo_profile = {
23
+ ...input_data.config.algoritmo,
24
+ available_blocks: input_data.available_blocks
25
+ }
26
+ Cargo_Profile.read_cargo_profile(cargo_profile)
27
+ }
@@ -0,0 +1,36 @@
1
+ const Slot = require('../../models/Slot')
2
+
3
+ /**
4
+ * Per-axis stacking: lower positive face, upper start, footprint on the other two dimensions.
5
+ */
6
+ const ALIGN_FLUSH_AXIS = {
7
+ z: {
8
+ lower_face_end: s => s.get_z() + s.get_length(),
9
+ start: s => s.get_z(),
10
+ size: s => s.get_length(),
11
+ min: b => b.min_z,
12
+ max: b => b.max_z,
13
+ footprint_key: s => `${s.get_x()}|${s.get_y()}|${s.get_width()}|${s.get_height()}`,
14
+ with_start: (s, v) => new Slot(s.get_x(), s.get_y(), v, s.get_width(), s.get_height(), s.get_length())
15
+ },
16
+ x: {
17
+ lower_face_end: s => s.get_x() + s.get_width(),
18
+ start: s => s.get_x(),
19
+ size: s => s.get_width(),
20
+ min: b => b.min_x,
21
+ max: b => b.max_x,
22
+ footprint_key: s => `${s.get_y()}|${s.get_z()}|${s.get_height()}|${s.get_length()}`,
23
+ with_start: (s, v) => new Slot(v, s.get_y(), s.get_z(), s.get_width(), s.get_height(), s.get_length())
24
+ },
25
+ y: {
26
+ lower_face_end: s => s.get_y() + s.get_height(),
27
+ start: s => s.get_y(),
28
+ size: s => s.get_height(),
29
+ min: b => b.min_y,
30
+ max: b => b.max_y,
31
+ footprint_key: s => `${s.get_x()}|${s.get_z()}|${s.get_width()}|${s.get_length()}`,
32
+ with_start: (s, v) => new Slot(s.get_x(), v, s.get_z(), s.get_width(), s.get_height(), s.get_length())
33
+ }
34
+ }
35
+
36
+ module.exports = { ALIGN_FLUSH_AXIS }
@@ -0,0 +1,112 @@
1
+ const Slot = require('../../models/Slot')
2
+ const { ALIGN_FLUSH_AXIS } = require('./align_flush_axis_config')
3
+
4
+ function align_flush_axes_one_round(slot_list, bounds, tolerance)
5
+ {
6
+ let working = slot_list
7
+ working = align_flush_axis_pass(working, bounds, tolerance, 'z')
8
+ working = align_flush_axis_pass(working, bounds, tolerance, 'x')
9
+ working = align_flush_axis_pass(working, bounds, tolerance, 'y')
10
+ return working
11
+ }
12
+
13
+ function align_flush_axis_pass(slot_list, bounds, tolerance, axis_key)
14
+ {
15
+ const cfg = ALIGN_FLUSH_AXIS[axis_key]
16
+ const snapshot = slot_list
17
+ const footprint_index = build_footprint_index(snapshot, cfg)
18
+ const next_slot_list = []
19
+ for (let upper_index = 0; upper_index < snapshot.length; upper_index++)
20
+ {
21
+ const upper_slot = snapshot[upper_index]
22
+ const bucket = footprint_index.get(cfg.footprint_key(upper_slot))
23
+ const best = find_best_lower_face_end(snapshot, upper_index, cfg, tolerance, bucket)
24
+ if (best === null)
25
+ {
26
+ next_slot_list.push(clone_slot_xyz(upper_slot))
27
+ continue
28
+ }
29
+ const clamped = clamp_start(best + tolerance, cfg.size(upper_slot), cfg.min(bounds), cfg.max(bounds))
30
+ next_slot_list.push(cfg.with_start(upper_slot, clamped))
31
+ }
32
+ return next_slot_list
33
+ }
34
+
35
+ function build_footprint_index(snapshot, cfg)
36
+ {
37
+ const index = new Map()
38
+ for (let i = 0; i < snapshot.length; i++)
39
+ {
40
+ const key = cfg.footprint_key(snapshot[i])
41
+ let bucket = index.get(key)
42
+ if (bucket === undefined)
43
+ {
44
+ bucket = []
45
+ index.set(key, bucket)
46
+ }
47
+ bucket.push(i)
48
+ }
49
+ return index
50
+ }
51
+
52
+ function find_best_lower_face_end(snapshot, upper_index, cfg, tolerance, bucket)
53
+ {
54
+ const upper_slot = snapshot[upper_index]
55
+ let best = null
56
+ for (const lower_index of bucket)
57
+ {
58
+ if (lower_index === upper_index)
59
+ {
60
+ continue
61
+ }
62
+ const candidate = evaluate_lower_candidate(upper_slot, snapshot[lower_index], cfg, tolerance)
63
+ if (candidate === null)
64
+ {
65
+ continue
66
+ }
67
+ if (best === null || candidate > best)
68
+ {
69
+ best = candidate
70
+ }
71
+ }
72
+ return best
73
+ }
74
+
75
+ function evaluate_lower_candidate(upper_slot, lower_slot, cfg, tolerance)
76
+ {
77
+ const lower_face_end = cfg.lower_face_end(lower_slot)
78
+ const upper_start = cfg.start(upper_slot)
79
+ if (lower_face_end > upper_start + tolerance)
80
+ {
81
+ return null
82
+ }
83
+ if (Math.abs(upper_start - lower_face_end) > tolerance)
84
+ {
85
+ return null
86
+ }
87
+ return lower_face_end
88
+ }
89
+
90
+ function clamp_start(start, size, min_value, max_value)
91
+ {
92
+ const max_start = max_value - size
93
+ if (max_start < min_value)
94
+ {
95
+ return min_value
96
+ }
97
+ return Math.min(Math.max(start, min_value), max_start)
98
+ }
99
+
100
+ function clone_slot_xyz(slot)
101
+ {
102
+ return new Slot(
103
+ slot.get_x(),
104
+ slot.get_y(),
105
+ slot.get_z(),
106
+ slot.get_width(),
107
+ slot.get_height(),
108
+ slot.get_length()
109
+ )
110
+ }
111
+
112
+ module.exports = { align_flush_axes_one_round }
@@ -0,0 +1,67 @@
1
+ const Slot = require('../../models/Slot')
2
+ const { align_flush_axes_one_round } = require('./align_flush_axis_single_round')
3
+
4
+ const FLOAT_EPSILON = 1e-9
5
+
6
+ /**
7
+ * @param {import('../../models/Slot')[]} slot_list_a
8
+ * @param {import('../../models/Slot')[]} slot_list_b
9
+ * @returns {boolean}
10
+ */
11
+ function are_slot_lists_xyz_equal(slot_list_a, slot_list_b)
12
+ {
13
+ if (slot_list_a.length !== slot_list_b.length)
14
+ {
15
+ return false
16
+ }
17
+ for (let index = 0; index < slot_list_a.length; index++)
18
+ {
19
+ const a = slot_list_a[index]
20
+ const b = slot_list_b[index]
21
+ const same = Math.abs(a.get_x() - b.get_x()) <= FLOAT_EPSILON
22
+ && Math.abs(a.get_y() - b.get_y()) <= FLOAT_EPSILON
23
+ && Math.abs(a.get_z() - b.get_z()) <= FLOAT_EPSILON
24
+ if (!same)
25
+ {
26
+ return false
27
+ }
28
+ }
29
+ return true
30
+ }
31
+
32
+ /**
33
+ * Applies z, then x, then y per round; repeats until stable or `max_rounds`.
34
+ *
35
+ * @param {import('../../models/Slot')[]} slot_list
36
+ * @param {{ min_x: number, max_x: number, min_y: number, max_y: number, min_z: number, max_z: number }} bounds
37
+ * @param {number} tolerance
38
+ * @param {number} max_rounds
39
+ * @returns {import('../../models/Slot')[]}
40
+ */
41
+ function align_flush_stacked_slots_stable(slot_list, bounds, tolerance, max_rounds)
42
+ {
43
+ let current = slot_list.map(slot => new Slot(
44
+ slot.get_x(),
45
+ slot.get_y(),
46
+ slot.get_z(),
47
+ slot.get_width(),
48
+ slot.get_height(),
49
+ slot.get_length()
50
+ ))
51
+ for (let round = 0; round < max_rounds; round++)
52
+ {
53
+ const snapshot = current
54
+ const next = align_flush_axes_one_round(snapshot, bounds, tolerance)
55
+ if (are_slot_lists_xyz_equal(next, snapshot))
56
+ {
57
+ return next
58
+ }
59
+ current = next
60
+ }
61
+ return current
62
+ }
63
+
64
+ module.exports = {
65
+ align_flush_stacked_slots_stable,
66
+ are_slot_lists_xyz_equal
67
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @param {import('../../models/Slot')[]} slot_list
3
+ * @returns {boolean} True when any pair of slots has positive-volume overlap.
4
+ */
5
+ function slot_list_has_overlapped_slots(slot_list)
6
+ {
7
+ for (let i = 0; i < slot_list.length; i++)
8
+ {
9
+ for (let j = i + 1; j < slot_list.length; j++)
10
+ {
11
+ const slot_a = slot_list[i]
12
+ const slot_b = slot_list[j]
13
+ if (slot_a.contains(slot_b) || slot_b.contains(slot_a))
14
+ {
15
+ return true
16
+ }
17
+ }
18
+ }
19
+ return false
20
+ }
21
+
22
+ module.exports = {
23
+ slot_list_has_overlapped_slots
24
+ }
@@ -0,0 +1,38 @@
1
+ const { evaluate_parallelepiped_shell_faces } = require('./shell_face_coverage')
2
+
3
+ /**
4
+ * @param {import('../../models/Slot')[]} slot_list
5
+ * @param {{ min_x: number, max_x: number, min_y: number, max_y: number, min_z: number, max_z: number }} bounds
6
+ * @param {number} tolerance
7
+ * @returns {boolean}
8
+ */
9
+ function has_parallelepiped_shell(slot_list, bounds, tolerance)
10
+ {
11
+ return evaluate_parallelepiped_shell_faces(slot_list, bounds, tolerance)
12
+ }
13
+
14
+ /**
15
+ * @param {import('../../models/Slot')[]} slot_list
16
+ * @param {{ min_x: number, max_x: number, min_y: number, max_y: number, min_z: number, max_z: number }} bounds
17
+ * @param {number} tolerance
18
+ * @returns {boolean}
19
+ */
20
+ function are_all_slots_inside_bounds(slot_list, bounds, tolerance)
21
+ {
22
+ return slot_list.every(slot =>
23
+ {
24
+ const slot_end = slot.get_end_point()
25
+ const lower_x = slot.get_x() >= bounds.min_x - tolerance
26
+ const lower_y = slot.get_y() >= bounds.min_y - tolerance
27
+ const lower_z = slot.get_z() >= bounds.min_z - tolerance
28
+ const upper_x = slot_end.x <= bounds.max_x + tolerance
29
+ const upper_y = slot_end.y <= bounds.max_y + tolerance
30
+ const upper_z = slot_end.z <= bounds.max_z + tolerance
31
+ return lower_x && lower_y && lower_z && upper_x && upper_y && upper_z
32
+ })
33
+ }
34
+
35
+ module.exports = {
36
+ has_parallelepiped_shell,
37
+ are_all_slots_inside_bounds
38
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Checks whether a rectangular area is fully covered by the union of a list
3
+ * of rectangles, allowing each rectangle to be expanded by `tolerance` on
4
+ * every side. The check builds a coordinate grid from the rectangle edges
5
+ * and marks every cell that has at least one covering rectangle.
6
+ *
7
+ * @param {{ min_a: number, max_a: number, min_b: number, max_b: number }} area
8
+ * @param {Array<{ start_a: number, end_a: number, start_b: number, end_b: number }>} rectangle_list
9
+ * @param {number} tolerance
10
+ * @returns {boolean}
11
+ */
12
+ function is_rectangle_fully_covered(area, rectangle_list, tolerance)
13
+ {
14
+ const axis_a_list = create_axis_list(area.min_a, area.max_a, rectangle_list, 'a')
15
+ const axis_b_list = create_axis_list(area.min_b, area.max_b, rectangle_list, 'b')
16
+ const cols = axis_a_list.length - 1
17
+ const rows = axis_b_list.length - 1
18
+ const grid = new Uint8Array(cols * rows)
19
+ for (const rectangle of rectangle_list)
20
+ {
21
+ mark_rectangle_cells(grid, rectangle, axis_a_list, axis_b_list, tolerance)
22
+ }
23
+ return is_grid_fully_marked(grid)
24
+ }
25
+
26
+ function create_axis_list(min_value, max_value, rectangle_list, suffix)
27
+ {
28
+ const axis_set = new Set([min_value, max_value])
29
+ for (const rectangle of rectangle_list)
30
+ {
31
+ axis_set.add(rectangle[`start_${suffix}`])
32
+ axis_set.add(rectangle[`end_${suffix}`])
33
+ }
34
+ return [...axis_set].sort((a, b) => a - b)
35
+ }
36
+
37
+ function mark_rectangle_cells(grid, rectangle, axis_a_list, axis_b_list, tolerance)
38
+ {
39
+ const i_start = find_first_covered_cell(axis_a_list, rectangle.start_a - tolerance)
40
+ const i_end = find_last_covered_cell(axis_a_list, rectangle.end_a + tolerance)
41
+ const j_start = find_first_covered_cell(axis_b_list, rectangle.start_b - tolerance)
42
+ const j_end = find_last_covered_cell(axis_b_list, rectangle.end_b + tolerance)
43
+ if (i_start > i_end || j_start > j_end)
44
+ {
45
+ return
46
+ }
47
+ const cols = axis_a_list.length - 1
48
+ for (let j = j_start; j <= j_end; j++)
49
+ {
50
+ const row_offset = j * cols
51
+ for (let i = i_start; i <= i_end; i++)
52
+ {
53
+ grid[row_offset + i] = 1
54
+ }
55
+ }
56
+ }
57
+
58
+ function find_first_covered_cell(axis_list, lower_bound)
59
+ {
60
+ const cell_count = axis_list.length - 1
61
+ let low = 0
62
+ let high = cell_count
63
+ while (low < high)
64
+ {
65
+ const mid = (low + high) >>> 1
66
+ const midpoint = (axis_list[mid] + axis_list[mid + 1]) / 2
67
+ if (midpoint >= lower_bound)
68
+ {
69
+ high = mid
70
+ }
71
+ else
72
+ {
73
+ low = mid + 1
74
+ }
75
+ }
76
+ return low
77
+ }
78
+
79
+ function find_last_covered_cell(axis_list, upper_bound)
80
+ {
81
+ const cell_count = axis_list.length - 1
82
+ let low = -1
83
+ let high = cell_count - 1
84
+ while (low < high)
85
+ {
86
+ const mid = (low + high + 1) >>> 1
87
+ const midpoint = (axis_list[mid] + axis_list[mid + 1]) / 2
88
+ if (midpoint <= upper_bound)
89
+ {
90
+ low = mid
91
+ }
92
+ else
93
+ {
94
+ high = mid - 1
95
+ }
96
+ }
97
+ return low
98
+ }
99
+
100
+ function is_grid_fully_marked(grid)
101
+ {
102
+ for (let index = 0; index < grid.length; index++)
103
+ {
104
+ if (grid[index] === 0)
105
+ {
106
+ return false
107
+ }
108
+ }
109
+ return true
110
+ }
111
+
112
+ module.exports = { is_rectangle_fully_covered }
@@ -0,0 +1,64 @@
1
+ const { is_rectangle_fully_covered } = require('./rectangle_coverage')
2
+
3
+ /**
4
+ * @param {import('../../models/Slot')[]} slot_list
5
+ * @param {{ min_x: number, max_x: number, min_y: number, max_y: number, min_z: number, max_z: number }} bounds
6
+ * @param {number} tolerance
7
+ * @returns {boolean}
8
+ */
9
+ function evaluate_parallelepiped_shell_faces(slot_list, bounds, tolerance)
10
+ {
11
+ return face_has_full_coverage(slot_list, bounds, 'y', bounds.min_y, 'x', 'z', tolerance)
12
+ && face_has_full_coverage(slot_list, bounds, 'y_end', bounds.max_y, 'x', 'z', tolerance)
13
+ && face_has_full_coverage(slot_list, bounds, 'x', bounds.min_x, 'y', 'z', tolerance)
14
+ && face_has_full_coverage(slot_list, bounds, 'x_end', bounds.max_x, 'y', 'z', tolerance)
15
+ && face_has_full_coverage(slot_list, bounds, 'z', bounds.min_z, 'x', 'y', tolerance)
16
+ && face_has_full_coverage(slot_list, bounds, 'z_end', bounds.max_z, 'x', 'y', tolerance)
17
+ }
18
+
19
+ function face_has_full_coverage(slot_list, bounds, plane, plane_value, axis_a, axis_b, tolerance)
20
+ {
21
+ const rectangle_list = collect_face_rectangles(slot_list, plane, plane_value, axis_a, axis_b, tolerance)
22
+ if (rectangle_list.length === 0)
23
+ {
24
+ return false
25
+ }
26
+ const area = { min_a: bounds[`min_${axis_a}`], max_a: bounds[`max_${axis_a}`], min_b: bounds[`min_${axis_b}`], max_b: bounds[`max_${axis_b}`] }
27
+ return is_rectangle_fully_covered(area, rectangle_list, tolerance)
28
+ }
29
+
30
+ function collect_face_rectangles(slot_list, plane, plane_value, axis_a, axis_b, tolerance)
31
+ {
32
+ const rectangle_list = []
33
+ for (const slot of slot_list)
34
+ {
35
+ if (!is_slot_on_plane(slot, plane, plane_value, tolerance))
36
+ {
37
+ continue
38
+ }
39
+ rectangle_list.push({
40
+ start_a: slot[`get_${axis_a}`](),
41
+ end_a: slot[`get_${axis_a}`]() + slot[`get_${size_axis(axis_a)}`](),
42
+ start_b: slot[`get_${axis_b}`](),
43
+ end_b: slot[`get_${axis_b}`]() + slot[`get_${size_axis(axis_b)}`]()
44
+ })
45
+ }
46
+ return rectangle_list
47
+ }
48
+
49
+ function is_slot_on_plane(slot, plane, plane_value, tolerance)
50
+ {
51
+ if (plane === 'x' || plane === 'y' || plane === 'z')
52
+ {
53
+ return Math.abs(slot[`get_${plane}`]() - plane_value) <= tolerance
54
+ }
55
+ const axis = plane.replace('_end', '')
56
+ return Math.abs(slot.get_end_point()[axis] - plane_value) <= tolerance
57
+ }
58
+
59
+ function size_axis(axis)
60
+ {
61
+ return axis === 'y' ? 'height' : axis === 'x' ? 'width' : 'length'
62
+ }
63
+
64
+ module.exports = { evaluate_parallelepiped_shell_faces }
@@ -0,0 +1,104 @@
1
+ const Slot = require('../../models/Slot')
2
+
3
+ /**
4
+ * Repeats bounds → anchor → align flush → normalize until `has_parallelepiped_shell` passes,
5
+ * or positions stabilize, or `max_iterations` is reached. Only translations (no new slots).
6
+ *
7
+ * @param {object} params
8
+ * @param {number} params.max_iterations
9
+ * @param {number} params.touch_tolerance
10
+ * @param {number} params.align_flush_max_rounds
11
+ * @param {import('../../models/Slot')[]} params.slot_list
12
+ * @param {function} params.get_bounds
13
+ * @param {function} params.anchor_slots_to_bounds
14
+ * @param {function} params.align_flush_stacked_slots_stable
15
+ * @param {function} params.normalize_slot_list
16
+ * @param {function} params.are_all_slots_inside_bounds
17
+ * @param {function} params.has_parallelepiped_shell
18
+ * @param {function} params.are_slot_lists_xyz_equal
19
+ * @returns {{ normalized_slot_list: import('../../models/Slot')[], normalized_bounds: object, anchor_align_changed: boolean }}
20
+ */
21
+ function run_shell_snap_convergence(params)
22
+ {
23
+ const {
24
+ slot_list,
25
+ max_iterations,
26
+ touch_tolerance,
27
+ align_flush_max_rounds,
28
+ get_bounds,
29
+ anchor_slots_to_bounds,
30
+ align_flush_stacked_slots_stable,
31
+ normalize_slot_list,
32
+ are_all_slots_inside_bounds,
33
+ has_parallelepiped_shell,
34
+ are_slot_lists_xyz_equal
35
+ } = params
36
+ let working = clone_slot_list(slot_list)
37
+ let anchor_align_changed = false
38
+ let previous_normalized = null
39
+ for (let iteration = 0; iteration < max_iterations; iteration++)
40
+ {
41
+ const bounds = get_bounds(working)
42
+ const anchored_slot_list = anchor_slots_to_bounds(working, bounds)
43
+ if (!are_slot_lists_xyz_equal(working, anchored_slot_list))
44
+ {
45
+ anchor_align_changed = true
46
+ }
47
+ const anchored_bounds = get_bounds(anchored_slot_list)
48
+ const aligned_slot_list = align_flush_stacked_slots_stable(
49
+ anchored_slot_list,
50
+ anchored_bounds,
51
+ touch_tolerance,
52
+ align_flush_max_rounds
53
+ )
54
+ if (!are_slot_lists_xyz_equal(anchored_slot_list, aligned_slot_list))
55
+ {
56
+ anchor_align_changed = true
57
+ }
58
+ const aligned_bounds = get_bounds(aligned_slot_list)
59
+ const normalized_slot_list = normalize_slot_list(aligned_slot_list, aligned_bounds)
60
+ const normalized_bounds = get_bounds(normalized_slot_list)
61
+ working = normalized_slot_list
62
+ const slot_list_inside_bounds = are_all_slots_inside_bounds(working, normalized_bounds)
63
+ const shell_ok = has_parallelepiped_shell(working, normalized_bounds)
64
+ if (slot_list_inside_bounds && shell_ok)
65
+ {
66
+ return {
67
+ normalized_slot_list: working,
68
+ normalized_bounds,
69
+ anchor_align_changed
70
+ }
71
+ }
72
+ if (previous_normalized !== null && are_slot_lists_xyz_equal(previous_normalized, working))
73
+ {
74
+ return {
75
+ normalized_slot_list: working,
76
+ normalized_bounds,
77
+ anchor_align_changed
78
+ }
79
+ }
80
+ previous_normalized = clone_slot_list(working)
81
+ }
82
+ const final_bounds = get_bounds(working)
83
+ return {
84
+ normalized_slot_list: working,
85
+ normalized_bounds: final_bounds,
86
+ anchor_align_changed
87
+ }
88
+ }
89
+
90
+ function clone_slot_list(slot_list)
91
+ {
92
+ return slot_list.map(slot => new Slot(
93
+ slot.get_x(),
94
+ slot.get_y(),
95
+ slot.get_z(),
96
+ slot.get_width(),
97
+ slot.get_height(),
98
+ slot.get_length()
99
+ ))
100
+ }
101
+
102
+ module.exports = {
103
+ run_shell_snap_convergence
104
+ }
@@ -0,0 +1,57 @@
1
+ const {Block} = require('../../models/Block')
2
+ const Slot = require('../../models/Slot')
3
+ const Failed_To_Create_Block_Exception = require('./exceptions/Failed_To_Create_Block_Exception')
4
+
5
+ const transform_blocks_data_into_object = function transform_blocks_data_into_object(block_data_list)
6
+ {
7
+ if (block_data_list.length === 0)
8
+ {
9
+ throw new Failed_To_Create_Block_Exception()
10
+ }
11
+ return block_data_list.map(block => create_block(block))
12
+ }
13
+
14
+ function create_block(block_data)
15
+ {
16
+ const slot_list = create_slot_list_of_a_block(block_data.slot_list)
17
+ return new Block(block_data, slot_list)
18
+ }
19
+
20
+ function create_slot_list_of_a_block(slot_data_list)
21
+ {
22
+ return slot_data_list.map(slot_data => create_slot(slot_data))
23
+ }
24
+
25
+ /**
26
+ * Reads slot height from JSON (`height` preferred; accepts common typo `heigth`).
27
+ *
28
+ * @param {object} item_data
29
+ * @returns {number|undefined}
30
+ */
31
+ function read_slot_height(item_data)
32
+ {
33
+ if (item_data.height !== undefined && item_data.height !== null)
34
+ {
35
+ return item_data.height
36
+ }
37
+ if (item_data.heigth !== undefined && item_data.heigth !== null)
38
+ {
39
+ return item_data.heigth
40
+ }
41
+ return undefined
42
+ }
43
+
44
+ function create_slot(item_data)
45
+ {
46
+ return new Slot(
47
+ item_data.x,
48
+ item_data.y,
49
+ item_data.z,
50
+ item_data.width,
51
+ read_slot_height(item_data),
52
+ item_data.length,
53
+ )
54
+ }
55
+
56
+ module.exports = transform_blocks_data_into_object
57
+ module.exports.read_slot_height = read_slot_height