@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.
- package/README.md +103 -2
- package/package.json +67 -5
- package/src/Allocation_Attempt.js +135 -0
- package/src/Allocation_Error_Handler.js +69 -0
- package/src/Allocation_Flow.js +162 -0
- package/src/Allocation_Optimization/Allocation_LP.js +150 -0
- package/src/Allocation_Optimization/Block_Allocator.js +129 -0
- package/src/Allocation_Optimization/Block_Layer_Order.js +50 -0
- package/src/Allocation_Optimization/Block_Potential_Weight.js +54 -0
- package/src/Allocation_Optimization/Chosen_Blocks_Stock_Cap.js +82 -0
- package/src/Allocation_Optimization/block_builder/Allocation_Item_Creator.js +37 -0
- package/src/Allocation_Optimization/block_builder/Block_Item_List_Validator.js +18 -0
- package/src/Allocation_Optimization/block_builder/Block_Wall_Builder.js +303 -0
- package/src/Allocation_Optimization/block_builder/Blocks_Builder.js +40 -0
- package/src/Allocation_Optimization/block_builder/Next_Block_Position.js +33 -0
- package/src/Allocation_Optimization/block_builder/Slot_Item_Assigner.js +45 -0
- package/src/Allocation_Optimization/block_builder/Stacking_Validation.js +30 -0
- package/src/Allocation_Optimization/block_builder/assert_tie_ratio_block_matches_orientation_below.js +44 -0
- package/src/Allocation_Optimization/block_builder/block_shape_stock.js +129 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Empty_Block_Item_List_Exception.js +21 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Invalid_Stacking_Exception.js +14 -0
- package/src/Allocation_Optimization/block_builder/exceptions/No_Suitable_Item_Exception.js +16 -0
- package/src/Allocation_Optimization/block_builder/exceptions/Restricted_Block_Exception.js +21 -0
- package/src/Allocation_Optimization/block_builder/should_omit_block_group_id.js +29 -0
- package/src/Allocation_Optimization/block_builder/snap_elevated_block_wall_items.js +34 -0
- package/src/Allocation_Optimization/block_builder/stacking_rules_input.js +52 -0
- package/src/Allocation_Optimization/cap_chosen_blocks_by_shape_stock.js +110 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Preparer.js +21 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Selector.js +55 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Threshold_Resolver.js +28 -0
- package/src/Allocation_Optimization/density_groups/Adaptive_Density_Group_Thresholds.js +23 -0
- package/src/Allocation_Optimization/density_groups/Container_Utilization.js +67 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Partitioner.js +74 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Scheduler.js +168 -0
- package/src/Allocation_Optimization/density_groups/Density_Group_Stock.js +49 -0
- package/src/Allocation_Optimization/density_groups/Density_Groups_Strategy.js +26 -0
- package/src/Allocation_Optimization/density_groups/Item_Density_Calculator.js +20 -0
- package/src/Allocation_Optimization/density_groups/Lock_Weight_Ahead_Release.js +75 -0
- package/src/Allocation_Optimization/exceptions/Invalid_Item_Amount_Exception.js +17 -0
- package/src/Allocation_Optimization/exceptions/No_Valid_Allocation_Exception.js +14 -0
- package/src/Allocation_Optimization/exceptions/Optimization_Infeasible_Exception.js +14 -0
- package/src/Allocation_Optimization/functions/Measure_Reader.js +20 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Mode.js +25 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Cobination_Strategies.js +8 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Measure_Combination_Mode_Checkers.js +70 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Translation.js +22 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/Variable_Weight_Getter.js +85 -0
- package/src/Allocation_Optimization/functions/Weight_Getter/constants.js +16 -0
- package/src/Allocation_Optimization/functions/measure_to_optimize.js +6 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Capacity_Bias_Item_Order.js +76 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Choose_Item_Heuristic_Context.js +63 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Item_Chooser.js +159 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Item_For_Slot_Chooser.js +49 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Slot_Compatible_Items_Finder.js +88 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Slots_Items_Assigner.js +182 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Stack_Slot_Calculator.js +87 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/Weight_Slot_Distribution.js +72 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Empty_Slot_Exception.js +17 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/Item_Taller_Than_Limit_Exception.js +21 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Available_Items_Exception.js +14 -0
- package/src/Allocation_Optimization/item_consumption_heuristic/exceptions/No_Slots_For_Items_Exception.js +14 -0
- package/src/Allocation_Optimization/lp_model/Block_Weight_Calculator.js +31 -0
- package/src/Allocation_Optimization/lp_model/LP_Data_Processor.js +42 -0
- package/src/Allocation_Optimization/lp_model/LP_Item_Slot_Assignment.js +93 -0
- package/src/Allocation_Optimization/lp_model/LP_Result_Mapper.js +47 -0
- package/src/Allocation_Optimization/lp_model/model_builder/Dimension_Range_Helper.js +49 -0
- package/src/Allocation_Optimization/lp_model/model_builder/Item_Assignment_Variables.js +133 -0
- package/src/Allocation_Optimization/lp_model/model_builder/LP_Model_Builder.js +132 -0
- package/src/Allocation_Optimization/lp_model/model_builder/exceptions/Missing_Item_Stock_Exception.js +18 -0
- package/src/Allocation_Optimization/lp_model/model_builder/goal_function/Goal_Function_Creator.js +83 -0
- package/src/Allocation_Optimization/lp_model/model_builder/item_dimension_hashes.js +31 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Block_Item_Amount_Restriction.js +53 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Coherence_Restriction.js +65 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Container_Supported_Weight_Restriction.js +42 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Exact_Pass_Amount_Restriction.js +62 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Relational_Group_Restriction.js +97 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Single_Item_Type_Restriction.js +79 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Space_Restriction.js +47 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Unavailable_Block_Restriction.js +27 -0
- package/src/Allocation_Optimization/lp_model/model_builder/restrictions/Uniform_Block_Measure_Restriction.js +92 -0
- package/src/Allocation_Optimization/next_group_id_after_preloaded.js +30 -0
- package/src/Allocation_Optimization/preferential_blocks/Preferential_Block_Identifier.js +74 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/Key_Item_Mapper.js +49 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Almost_Unique_Item.js +31 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Cant_Stack_It_Self.js +68 -0
- package/src/Allocation_Optimization/preferential_blocks/key_item/rules/Rule_Interface.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Intercalation_State.js +49 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter.js +33 -0
- package/src/Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter.js +20 -0
- package/src/Allocation_Optimization/tie_ratio/collect_tie_ratio_orientations_below_footprint.js +64 -0
- package/src/Allocation_Optimization/tie_ratio/filter_blocks_by_orientation.js +17 -0
- package/src/Allocation_Optimization/tie_ratio/find_orientation_below_space.js +77 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/allocated_item_penetrates_any.js +31 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/apply_loose_placement_to_allocated_item.js +94 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/axis_overlap_length.js +16 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/block_local_origin.js +18 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/box_fits_inside_container.js +39 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_allocated_item_at_placement.js +18 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_placement_on_generic_supporter.js +64 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/build_slot_grid_from_cluster.js +66 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/compare_group_ids.js +20 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/container_with_pending_wall_items.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/empty_space_is_on_floor.js +16 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/finalize_loose_item_placement.js +58 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_best_generic_supporter_placement.js +58 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_next_free_slot_index.js +119 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_supporter_directly_below.js +51 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/find_tie_ratio_supporter_cluster.js +57 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/footprint_xz_overlap_area.js +26 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/item_fits_supporter_slot.js +22 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_footprint_region_from_options.js +24 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_fits_inside_container.js +21 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_item_has_geometric_support.js +21 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/loose_on_block_slot_state.js +88 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/placement_coords_fit_inside_container.js +34 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/read_empilhar_area_igual_from_allocation_item.js +12 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/realigned_loose_geometry_gates.js +25 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_on_generic_supporter.js +65 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_loose_placement_position.js +68 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_placement_y_at_slot.js +45 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/resolve_without_tie_ratio_cluster.js +79 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/select_tie_ratio_slot_placement.js +84 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/slot_footprint_collision.js +105 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_cluster_selection.js +119 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_footprint_overlap.js +56 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_placement_plane.js +109 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/tie_ratio_supporter_predicate.js +23 -0
- package/src/Allocation_Optimization/tie_ratio/loose_on_block/try_tie_ratio_slot_placement.js +62 -0
- package/src/Allocation_Optimization/tie_ratio/snap_stacked_items_to_floor_footprints.js +138 -0
- package/src/Allocation_Optimization/tie_ratio/supporters_by_top_y_index.js +78 -0
- package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_below_empty_space.js +89 -0
- package/src/Allocation_Optimization/tie_ratio/tie_ratio_orientation_from_group.js +48 -0
- package/src/Block_Management.js +34 -0
- package/src/Blocks_Preparation/Cube_Map_Function.js +27 -0
- package/src/Blocks_Wall_Allocation.js +3 -0
- package/src/IO/Answer_Status.js +4 -0
- package/src/IO/Output_Builder.js +35 -0
- package/src/IO/count_allocated_items.js +31 -0
- package/src/IO/create_error_response.js +62 -0
- package/src/IO/format_allocation_error_message.js +25 -0
- package/src/Item_Continuation_Lock.js +129 -0
- package/src/Item_Picking_Continuity.js +41 -0
- package/src/allocation_flow/chooser_session_state.js +21 -0
- package/src/allocation_flow/compound_probe_fallback.js +17 -0
- package/src/allocation_flow/container_remaining_capacity.js +23 -0
- package/src/allocation_flow/density_group_item_filter.js +31 -0
- package/src/allocation_flow/effective_item_fingerprint.js +14 -0
- package/src/allocation_flow/item_continuation_lock_gate.js +38 -0
- package/src/allocation_flow/no_space_left_recovery.js +48 -0
- package/src/allocation_flow/run_allocation_iteration.js +155 -0
- package/src/allocation_flow/space_skip_state.js +91 -0
- package/src/allocation_flow/try_no_space_left_recovery.js +50 -0
- package/src/exceptions/Invalid_Parameter_Exception.js +17 -0
- package/src/exceptions/Relational_Allocation_Incomplete_Exception.js +24 -0
- package/src/exceptions/Relational_Colocation_Violation_Exception.js +23 -0
- package/src/exceptions/Relational_Config_Mismatch_Exception.js +17 -0
- package/src/exceptions/There_Is_No_Block_Options_To_Allocate_Exception.js +14 -0
- package/src/index.js +6 -0
- package/src/input_preparation/Block_Formatter.js +179 -0
- package/src/input_preparation/Input_Creator.js +76 -0
- package/src/input_preparation/Input_State_Preparation.js +47 -0
- package/src/input_preparation/State_Builder.js +27 -0
- package/src/input_preparation/block_formatter/align_flush_axis_config.js +36 -0
- package/src/input_preparation/block_formatter/align_flush_axis_single_round.js +112 -0
- package/src/input_preparation/block_formatter/align_flush_stacked_slots.js +67 -0
- package/src/input_preparation/block_formatter/overlapped_slots.js +24 -0
- package/src/input_preparation/block_formatter/parallelepiped_shell.js +38 -0
- package/src/input_preparation/block_formatter/rectangle_coverage.js +112 -0
- package/src/input_preparation/block_formatter/shell_face_coverage.js +64 -0
- package/src/input_preparation/block_formatter/shell_snap_convergence.js +104 -0
- package/src/input_preparation/block_preparation/Block_Data_To_Object_Transformer.js +57 -0
- package/src/input_preparation/block_preparation/Block_Module_Name.js +17 -0
- package/src/input_preparation/block_preparation/Blocks_Creator.js +101 -0
- package/src/input_preparation/block_preparation/Blocksmith.js +19 -0
- package/src/input_preparation/block_preparation/block_modules/create_block_candidates.js +41 -0
- package/src/input_preparation/block_preparation/block_modules/manual_blocks.js +10 -0
- package/src/input_preparation/block_preparation/block_modules/module_registry.js +20 -0
- package/src/input_preparation/block_preparation/block_modules/run_creator.js +34 -0
- package/src/input_preparation/block_preparation/block_modules/single_item_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/spiral_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/tie_ratio_blocks.js +12 -0
- package/src/input_preparation/block_preparation/block_modules/tower_blocks.js +12 -0
- package/src/input_preparation/block_preparation/exceptions/Failed_To_Create_Block_Exception.js +14 -0
- package/src/input_preparation/block_preparation/exceptions/Failed_To_Retrieve_Block_Exception.js +17 -0
- package/src/input_preparation/block_preparation/exceptions/Missing_Object_Store_Exception.js +10 -0
- package/src/input_preparation/block_preparation/exceptions/No_Blocks_Were_Created_Exception.js +14 -0
- package/src/input_preparation/block_preparation/input/Input_Creator.js +96 -0
- package/src/input_preparation/block_preparation/manual_blocks/Manual_Blocks.js +95 -0
- package/src/input_preparation/build_empty_space_finder_options.js +43 -0
- package/src/input_preparation/item_preparation/Items_Reader.js +27 -0
- package/src/input_preparation/min_extents_from_items.js +29 -0
- package/src/input_preparation/stackability_index/Blocks_Stackability_Index_Calculator.js +58 -0
- package/src/input_preparation/stackability_index/Slots_Stackability_index_Calculator.js +28 -0
- package/src/input_preparation/stackability_index/Stackability_Input_Creator.js +27 -0
- package/src/input_preparation/stackability_index/stackability_index_pop_stack.js +81 -0
- package/src/input_preparation/stacking_constraints/Weight_Stacking_Validation.js +15 -0
- package/src/lp_optimizer_result_status.js +20 -0
- package/src/messages/Allocator_Message.js +42 -0
- package/src/messages/resolve_error_message_entry.js +57 -0
- package/src/models/Allocated_Item.js +136 -0
- package/src/models/Allocation_Item.js +219 -0
- package/src/models/Block.js +198 -0
- package/src/models/Cargo_Profile.js +418 -0
- package/src/models/Preloaded_Allocated_Item.js +132 -0
- package/src/models/Slot.js +67 -0
- package/src/models/Stacking_Rules.js +58 -0
- package/src/models/auxiliaryFunctions/Available_Block_Module_List_Creator.js +9 -0
- package/src/models/auxiliaryFunctions/Measure_Translator.js +24 -0
- package/src/models/auxiliaryFunctions/item_json_reader.js +44 -0
- package/src/models/item_json_reader.js +71 -0
- package/src/models/placed_item_record.js +70 -0
- package/src/models/preloaded_rotation_helpers.js +38 -0
- package/src/models/slots_have_same_measure.js +45 -0
- package/src/models/transport/Container.js +162 -0
- package/src/models/transport/Transport.js +62 -0
- package/src/models/transport/build_stacking_feasibility_checker.js +64 -0
- package/src/models/transport/container_stacking_checkpoint.js +42 -0
- package/src/models/transport/factory/Container_Factory.js +46 -0
- package/src/models/transport/factory/Corner_Casting_Factory.js +62 -0
- package/src/models/transport/factory/Previously_Allocated_Item_Factory.js +28 -0
- package/src/models/transport/factory/Transport_Factory.js +13 -0
- package/src/models/transport/items_for_empty_space_finder.js +91 -0
- package/src/models/transport/resolve_container_stacking_inputs.js +23 -0
- package/src/models/transport/stacking_input_from_wire.js +58 -0
- package/src/optimizer_connection_errors.js +50 -0
- package/src/relational/Relational_Error_Codes.js +7 -0
- package/src/relational/finalize_relational_allocation.js +20 -0
- package/src/relational/has_relational_items.js +11 -0
- package/src/relational/is_relational_error_code.js +15 -0
- package/src/relational/resolve_relational_container_sequences.js +29 -0
- package/src/run_core_allocation.js +118 -0
- package/src/space_and_block_chooser/Space_And_Blocks_Chooser.js +115 -0
- package/src/space_and_block_chooser/blocks_filters/Block_Filter_Interface.js +19 -0
- package/src/space_and_block_chooser/blocks_filters/Filter_Runner.js +46 -0
- package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Block_With_Overlapped_Slots_Filter.js +14 -0
- package/src/space_and_block_chooser/blocks_filters/initial_blocks_filter/Initial_Blocks_Filter_List.js +19 -0
- package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Blocks_Bigger_Than_Space_Filter.js +17 -0
- package/src/space_and_block_chooser/blocks_filters/pos_selection_filters/Post_Selection_Filter_List.js +9 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Insuficient_Items_Filter.js +81 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Pre_Selection_Filter_List.js +8 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Blocks_Lower_Than_Max_Tower_Height.js +23 -0
- package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/max_tower_height/Max_Tower_Height.js +82 -0
- package/src/space_and_block_chooser/build_allocated_item_snapshots.js +19 -0
- package/src/space_and_block_chooser/compound_first_empty_space_branch.js +61 -0
- package/src/space_and_block_chooser/compound_first_with_leftover_fill.js +142 -0
- package/src/space_and_block_chooser/compound_first_without_leftover_fill.js +56 -0
- package/src/space_and_block_chooser/empty_spaces_where_post_selection_keeps_blocks.js +83 -0
- package/src/space_and_block_chooser/exceptions/Invalid_Space_To_Allocate_Exception.js +14 -0
- package/src/space_and_block_chooser/leftover_space_memory.js +113 -0
- package/src/space_and_block_chooser/leftover_unitary_blocks.js +153 -0
- package/src/space_and_block_chooser/leftover_unitary_empty_spaces.js +135 -0
- package/src/space_and_block_chooser/probe_set_pool.js +35 -0
- package/src/space_and_block_chooser/run_space_and_block_selection_attempt.js +88 -0
- package/src/tools/Array_Validator.js +6 -0
- package/src/tools/Clone.js +27 -0
- package/src/tools/Hash.js +8 -0
- package/src/tools/Rounder.js +5 -0
- package/src/tools/String_To_Boolean.js +12 -0
- package/src/tools/cargo_profile/Cargo_Profile_Field_Value_Resolver.js +44 -0
- package/src/tools/compact_items_with_stock.js +9 -0
- package/src/tools/mm_to_allocation_domain.js +14 -0
- package/src/tracing/Allocation_Tracer.js +52 -0
- package/src/tracing/Trace_Context.js +18 -0
- package/src/tracing/trace_outcome.js +18 -0
- package/src/tracing/traced_step.js +57 -0
- package/src/validation/Item_Continuation_Lock_Flag.js +52 -0
- package/src/validation/Item_Validation.js +29 -0
- package/src/validation/Relational_Colocation_Validator.js +60 -0
- package/src/validation/Relational_Completeness_Validator.js +146 -0
- package/src/validation/Relational_Continuation_Lock_Validation.js +37 -0
- package/src/validation/Relational_Proportional_Normalizer.js +194 -0
- package/src/validation/Validation.js +9 -0
- package/src/validation/Validation_Runner.js +20 -0
- package/src/validation/exceptions/Invalid_Block_Module_Config_Exception.js +14 -0
- package/src/validation/exceptions/Invalid_Input_Exception.js +14 -0
- package/src/validation/exceptions/Invalid_Input_Type_Exception.js +14 -0
- package/src/validation/schemas/allocated_item_schema.js +18 -0
- package/src/validation/schemas/allocation_request_schema.js +178 -0
- package/src/validation/schemas/container_row_schema.js +16 -0
- package/src/validation/schemas/item_schema.js +60 -0
- package/src/validation/schemas/transport_env_schema.js +19 -0
- package/src/validation/validate_block_module_config.js +147 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If the optimizer call failed due to a peer-closed HTTP socket or a temporary
|
|
3
|
+
* NATS failure, returns a clearer Error; otherwise returns the original error.
|
|
4
|
+
* @param {Error} error - Error from `@jetta/lp-framework`.
|
|
5
|
+
* @param {number} elapsed_ms - Time spent in optimize() until failure.
|
|
6
|
+
* @param {number} block_count - Blocks in the LP model.
|
|
7
|
+
* @param {number} restriction_count - Restrictions registered on the optimizer instance.
|
|
8
|
+
* @returns {Error} Original or wrapped error.
|
|
9
|
+
*/
|
|
10
|
+
function enrich_optimizer_http_error(error, elapsed_ms, block_count, restriction_count)
|
|
11
|
+
{
|
|
12
|
+
const message = String(error?.message ?? '')
|
|
13
|
+
const is_socket_peer = error?.code === 'UND_ERR_SOCKET'
|
|
14
|
+
|| message.includes('other side closed')
|
|
15
|
+
const is_nats_temporary = error?.name === 'OptimizerNatsTemporaryError'
|
|
16
|
+
|| message.toLowerCase().includes('nats request failed')
|
|
17
|
+
|| message.toLowerCase().includes('no responders')
|
|
18
|
+
if (!is_socket_peer && !is_nats_temporary)
|
|
19
|
+
{
|
|
20
|
+
return error
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const model_context = `while solving an LP with ${block_count} blocks and ${restriction_count} restrictions`
|
|
24
|
+
const immediate_close_threshold_ms = 1000
|
|
25
|
+
let guidance
|
|
26
|
+
if (is_nats_temporary)
|
|
27
|
+
{
|
|
28
|
+
guidance = 'NATS request-reply timed out or had no responders '
|
|
29
|
+
+ '(worker scaled to zero, stream lag, or cold start). '
|
|
30
|
+
+ 'Wait for KEDA to scale python-optimizer-nats and/or raise OPTIMIZER_NATS_TIMEOUT_MS.'
|
|
31
|
+
}
|
|
32
|
+
else if (elapsed_ms < immediate_close_threshold_ms)
|
|
33
|
+
{
|
|
34
|
+
guidance = 'This usually means the optimizer connection was reset (pod restart, failed liveness/readiness probe, or dying endpoint), not a slow CPLEX solve.'
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
{
|
|
38
|
+
guidance = 'This is usually a server or proxy read/worker timeout on a large model. '
|
|
39
|
+
+ 'Raise the optimizer timeout, or reduce candidate blocks in the allocation input.'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const prefix = is_nats_temporary
|
|
43
|
+
? `Optimizer NATS request failed after ${elapsed_ms} ms`
|
|
44
|
+
: `Optimizer closed the HTTP connection after ${elapsed_ms} ms`
|
|
45
|
+
const wrapped = new Error(`${prefix} ${model_context}. ${guidance}`)
|
|
46
|
+
wrapped.cause = error
|
|
47
|
+
return wrapped
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { enrich_optimizer_http_error }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { validate_transport_colocation } = require('../validation/Relational_Colocation_Validator')
|
|
2
|
+
const { validate_relational_completeness } = require('../validation/Relational_Completeness_Validator')
|
|
3
|
+
const {
|
|
4
|
+
normalize_relational_proportional_allocation
|
|
5
|
+
} = require('../validation/Relational_Proportional_Normalizer')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Normalizes proportional relational amounts and validates completeness and co-location.
|
|
9
|
+
* @param {object} transport - Allocated transport to finalize.
|
|
10
|
+
* @param {object[]} item_list - Remaining items after allocation (may be empty).
|
|
11
|
+
* @returns {void}
|
|
12
|
+
*/
|
|
13
|
+
function finalize_relational_allocation(transport, item_list)
|
|
14
|
+
{
|
|
15
|
+
normalize_relational_proportional_allocation(transport, item_list)
|
|
16
|
+
validate_relational_completeness(transport, item_list)
|
|
17
|
+
validate_transport_colocation(transport)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = finalize_relational_allocation
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether any item in the list belongs to a relational group.
|
|
3
|
+
* @param {object[]} item_list
|
|
4
|
+
* @returns {boolean}
|
|
5
|
+
*/
|
|
6
|
+
function has_relational_items(item_list)
|
|
7
|
+
{
|
|
8
|
+
return item_list.some(item => item.get_relational_group_id && item.get_relational_group_id())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = has_relational_items
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const RELATION_ERROR_CODES = require('./Relational_Error_Codes')
|
|
2
|
+
|
|
3
|
+
const RELATIONAL_ERROR_CODE_SET = new Set(Object.values(RELATION_ERROR_CODES))
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Whether a value is a known relational allocation error code.
|
|
7
|
+
* @param {unknown} code
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
*/
|
|
10
|
+
function is_relational_error_code(code)
|
|
11
|
+
{
|
|
12
|
+
return RELATIONAL_ERROR_CODE_SET.has(code)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = is_relational_error_code
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const Cargo_Profile = require('../models/Cargo_Profile')
|
|
2
|
+
const has_relational_items = require('./has_relational_items')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns container sequences to allocate. When relational co-location is enforced
|
|
6
|
+
* and relational items remain, only the first container sequence is used.
|
|
7
|
+
* @param {object} transport - Allocation transport with container sequences.
|
|
8
|
+
* @param {object[]} item_list - Items still to allocate.
|
|
9
|
+
* @returns {Array<number|string>} Container sequence list for this allocate pass.
|
|
10
|
+
*/
|
|
11
|
+
function resolve_relational_container_sequences(transport, item_list)
|
|
12
|
+
{
|
|
13
|
+
const all_sequences = transport.get_container_sequence_list()
|
|
14
|
+
|
|
15
|
+
if (!Cargo_Profile.enforce_relational_group_co_location())
|
|
16
|
+
{
|
|
17
|
+
return all_sequences
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const has_relational_items_present = has_relational_items(item_list)
|
|
21
|
+
if (!has_relational_items_present || all_sequences.length === 0)
|
|
22
|
+
{
|
|
23
|
+
return all_sequences
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return [all_sequences[0]]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = resolve_relational_container_sequences
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const { performance } = require('perf_hooks')
|
|
2
|
+
const Allocation_Flow = require('./Allocation_Flow')
|
|
3
|
+
const build_input_state = require('./input_preparation/State_Builder')
|
|
4
|
+
const { SUCCESS, ERROR } = require('./IO/Answer_Status')
|
|
5
|
+
const build_output_answer = require('./IO/Output_Builder')
|
|
6
|
+
const run_validations = require('./validation/Validation_Runner')
|
|
7
|
+
const Config = require('./models/Cargo_Profile')
|
|
8
|
+
const { Logger } = require('@jetta/logger')
|
|
9
|
+
const {
|
|
10
|
+
count_allocated_items_in_transport,
|
|
11
|
+
count_preloaded_items_in_input,
|
|
12
|
+
} = require('./IO/count_allocated_items')
|
|
13
|
+
const { parse_allocation_request } = require('./validation/schemas/allocation_request_schema')
|
|
14
|
+
const create_error_response = require('./IO/create_error_response')
|
|
15
|
+
const { run_with_existing_tracer, get_tracer } = require('./tracing/Allocation_Tracer')
|
|
16
|
+
const { TRACE_CONTEXT } = require('./tracing/Trace_Context')
|
|
17
|
+
|
|
18
|
+
const logger = new Logger('Blocks Wall Allocation')
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Runs one allocation request.
|
|
22
|
+
* @param {object} input_data
|
|
23
|
+
* @param {{ object_store?: { get_object: Function }, tracer?: object }} [dependencies]
|
|
24
|
+
* @returns {Promise<string>}
|
|
25
|
+
*/
|
|
26
|
+
async function run_core_allocation(input_data, dependencies = {})
|
|
27
|
+
{
|
|
28
|
+
const execute = () => run_blocks_wall_allocation(input_data, dependencies)
|
|
29
|
+
if (dependencies.tracer)
|
|
30
|
+
{
|
|
31
|
+
return run_with_existing_tracer(dependencies.tracer, execute)
|
|
32
|
+
}
|
|
33
|
+
return execute()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {object} input_data
|
|
38
|
+
* @param {{ object_store?: { get_object: Function } }} dependencies
|
|
39
|
+
* @returns {Promise<string>}
|
|
40
|
+
*/
|
|
41
|
+
async function run_blocks_wall_allocation(input_data, dependencies)
|
|
42
|
+
{
|
|
43
|
+
const start_time = performance.now()
|
|
44
|
+
const tracer = get_tracer()
|
|
45
|
+
const tx_id = tracer?.start_transaction(TRACE_CONTEXT.MAIN_FLOW)
|
|
46
|
+
try
|
|
47
|
+
{
|
|
48
|
+
const output = await allocate_request(input_data, dependencies)
|
|
49
|
+
return finish_success(start_time, tracer, tx_id, output)
|
|
50
|
+
}
|
|
51
|
+
catch (error)
|
|
52
|
+
{
|
|
53
|
+
return finish_failure(start_time, tracer, tx_id, error)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {object} input_data
|
|
59
|
+
* @param {{ object_store?: { get_object: Function } }} dependencies
|
|
60
|
+
* @returns {Promise<string>}
|
|
61
|
+
*/
|
|
62
|
+
async function allocate_request(input_data, dependencies)
|
|
63
|
+
{
|
|
64
|
+
logger.log('request received.')
|
|
65
|
+
const safe_input = parse_allocation_request(input_data)
|
|
66
|
+
const items_to_allocate = safe_input.items.reduce((accumulator, item) => accumulator + item.qtd, 0)
|
|
67
|
+
logger.debug(`starting Blocks Wall Allocation request with ${items_to_allocate} items.`)
|
|
68
|
+
run_validations(safe_input)
|
|
69
|
+
const input_state = await build_input_state(safe_input, dependencies)
|
|
70
|
+
const flow = new Allocation_Flow(input_state)
|
|
71
|
+
const output_data = await flow.allocate()
|
|
72
|
+
const total_allocated = count_allocated_items_in_transport(output_data)
|
|
73
|
+
const preloaded_count = count_preloaded_items_in_input(safe_input)
|
|
74
|
+
logger.debug(`allocated a total of ${total_allocated - preloaded_count} items.`)
|
|
75
|
+
return build_output_answer(SUCCESS, output_data)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {number} start_time
|
|
80
|
+
* @param {object|null} tracer
|
|
81
|
+
* @param {string|undefined} tx_id
|
|
82
|
+
* @param {string} output
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
function finish_success(start_time, tracer, tx_id, output)
|
|
86
|
+
{
|
|
87
|
+
print_elapsed_time(start_time)
|
|
88
|
+
Config.reset()
|
|
89
|
+
logger.log('request finished successfully.')
|
|
90
|
+
tracer?.end_transaction_succesfully(tx_id)
|
|
91
|
+
return output
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {number} start_time
|
|
96
|
+
* @param {object|null} tracer
|
|
97
|
+
* @param {string|undefined} tx_id
|
|
98
|
+
* @param {Error} error
|
|
99
|
+
* @returns {string}
|
|
100
|
+
*/
|
|
101
|
+
function finish_failure(start_time, tracer, tx_id, error)
|
|
102
|
+
{
|
|
103
|
+
logger.error(error.message)
|
|
104
|
+
logger.error(error.stack)
|
|
105
|
+
print_elapsed_time(start_time)
|
|
106
|
+
Config.reset()
|
|
107
|
+
tracer?.end_transaction_with_failure(tx_id)
|
|
108
|
+
return build_output_answer(ERROR, create_error_response(error))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function print_elapsed_time(start_time)
|
|
112
|
+
{
|
|
113
|
+
const end_time = performance.now()
|
|
114
|
+
const elapsed_time = ((end_time - start_time) / 1000).toFixed(5)
|
|
115
|
+
logger.debug(`finished request in ${elapsed_time} seconds`)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = run_core_allocation
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const run_filters = require('./blocks_filters/Filter_Runner')
|
|
2
|
+
const run_space_and_block_selection_attempt = require('./run_space_and_block_selection_attempt')
|
|
3
|
+
const {NoSpaceLeftException} = require('@jetta/empty-spaces-manager')
|
|
4
|
+
const Invalid_Space_To_Allocate_Exception = require('./exceptions/Invalid_Space_To_Allocate_Exception')
|
|
5
|
+
const {Logger} = require('@jetta/logger')
|
|
6
|
+
const logger = new Logger('Space and Blocks Creator')
|
|
7
|
+
const { traced_step } = require('../tracing/traced_step')
|
|
8
|
+
const { TRACE_CONTEXT } = require('../tracing/Trace_Context')
|
|
9
|
+
|
|
10
|
+
function get_unattempted_space_list(empty_space_list, spaces_to_avoid)
|
|
11
|
+
{
|
|
12
|
+
const pending_spaces = []
|
|
13
|
+
for (const space of empty_space_list)
|
|
14
|
+
{
|
|
15
|
+
if (!spaces_to_avoid.has(space))
|
|
16
|
+
{
|
|
17
|
+
pending_spaces.push(space)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return pending_spaces
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function handle_invalid_space_exception(error, chosen_empty_space)
|
|
24
|
+
{
|
|
25
|
+
if (!(error instanceof Invalid_Space_To_Allocate_Exception))
|
|
26
|
+
{
|
|
27
|
+
throw error
|
|
28
|
+
}
|
|
29
|
+
if (chosen_empty_space === undefined)
|
|
30
|
+
{
|
|
31
|
+
throw new NoSpaceLeftException()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function remove_empty_space_from_pending_list(pending_list, chosen_empty_space)
|
|
36
|
+
{
|
|
37
|
+
const index = pending_list.indexOf(chosen_empty_space)
|
|
38
|
+
if (index > -1)
|
|
39
|
+
{
|
|
40
|
+
pending_list.splice(index, 1)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function process_space_and_blocks(filter_data, empty_space_list)
|
|
45
|
+
{
|
|
46
|
+
let chosen_empty_space
|
|
47
|
+
try
|
|
48
|
+
{
|
|
49
|
+
const outcome = await run_space_and_block_selection_attempt(run_filters, filter_data, empty_space_list)
|
|
50
|
+
chosen_empty_space = outcome.chosen_empty_space
|
|
51
|
+
if (outcome.pos_selection_block_list !== null)
|
|
52
|
+
{
|
|
53
|
+
return {
|
|
54
|
+
empty_space: chosen_empty_space,
|
|
55
|
+
block_list: outcome.pos_selection_block_list,
|
|
56
|
+
no_fillable_space_set: filter_data.no_fillable_space_set
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error)
|
|
61
|
+
{
|
|
62
|
+
handle_invalid_space_exception(error, chosen_empty_space)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
remove_empty_space_from_pending_list(empty_space_list, chosen_empty_space)
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Chooses an empty space and matching blocks for allocation.
|
|
71
|
+
* @param {object} container - Current transport container.
|
|
72
|
+
* @param {object[]} block_list - Candidate blocks.
|
|
73
|
+
* @param {object[]} item_list - Items to allocate in this iteration.
|
|
74
|
+
* @param {Set<object>} spaces_to_avoid - Spaces skipped for the current iteration view.
|
|
75
|
+
* @param {object} [chooser_session] - Optional persistent session from the allocation flow.
|
|
76
|
+
* @returns {Promise<{ empty_space: object, block_list: object[], no_fillable_space_set: Set<object> }>}
|
|
77
|
+
*/
|
|
78
|
+
module.exports = async function choose_space_and_blocks(
|
|
79
|
+
container,
|
|
80
|
+
block_list,
|
|
81
|
+
item_list,
|
|
82
|
+
spaces_to_avoid,
|
|
83
|
+
chooser_session
|
|
84
|
+
)
|
|
85
|
+
{
|
|
86
|
+
return traced_step(TRACE_CONTEXT.SPACE_AND_BLOCK_CHOICE, async () =>
|
|
87
|
+
{
|
|
88
|
+
logger.debug('choosing space and blocks')
|
|
89
|
+
const empty_space_list = get_unattempted_space_list(container.empty_spaces(), spaces_to_avoid)
|
|
90
|
+
const obligate_compound_session = chooser_session?.obligate_compound_session
|
|
91
|
+
?? { skip_compound_probe: false }
|
|
92
|
+
const filter_data = {
|
|
93
|
+
container,
|
|
94
|
+
block_list,
|
|
95
|
+
item_list,
|
|
96
|
+
spaces_to_avoid,
|
|
97
|
+
no_fillable_space_set: new Set(),
|
|
98
|
+
obligate_compound_session,
|
|
99
|
+
tie_ratio_intercalation_state: chooser_session?.tie_ratio_intercalation_state ?? null,
|
|
100
|
+
empty_space: undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
while (empty_space_list.length > 0)
|
|
104
|
+
{
|
|
105
|
+
filter_data.empty_space = undefined
|
|
106
|
+
const result = await process_space_and_blocks(filter_data, empty_space_list)
|
|
107
|
+
if (result)
|
|
108
|
+
{
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
throw new NoSpaceLeftException()
|
|
114
|
+
})
|
|
115
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Block_Filter_Interface
|
|
2
|
+
{
|
|
3
|
+
/**
|
|
4
|
+
* @description a virtual method to be implemented by all block filters"
|
|
5
|
+
* @param {Object} filter_data
|
|
6
|
+
* {
|
|
7
|
+
* container: Container,
|
|
8
|
+
* empty_space: Empty_Space,
|
|
9
|
+
* block_list: Array<Block>,
|
|
10
|
+
* item_list: Array<Item>
|
|
11
|
+
* }
|
|
12
|
+
* @return {Array<Block>} filtered block list
|
|
13
|
+
**/
|
|
14
|
+
static run(filter_data)
|
|
15
|
+
{
|
|
16
|
+
throw new Error('do not overrided pure virtual method, please implement on your extended class')
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
module.exports = Block_Filter_Interface
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const Invalid_Space_To_Allocate_Exception = require('../exceptions/Invalid_Space_To_Allocate_Exception')
|
|
2
|
+
const {Logger} = require('@jetta/logger')
|
|
3
|
+
const logger = new Logger('Filter Runner')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs a series of filters on a list of blocks, progressively reducing the list.
|
|
7
|
+
*
|
|
8
|
+
* This function iterates through a list of provided filters, passing a data object to each.
|
|
9
|
+
* Each filter returns a new, potentially smaller, list of blocks. If the final list of blocks
|
|
10
|
+
* is empty, it means no block could pass the filters for the given empty space. In this case,
|
|
11
|
+
* the space is marked as invalid and an exception is thrown to signal that this allocation path failed.
|
|
12
|
+
*
|
|
13
|
+
* @param {Array<{ run: function(Object): Array<Object> }>} filter_list Filters with a sync `run()` method.
|
|
14
|
+
* @param {Object} filter_data The data object required by the filters.
|
|
15
|
+
* @property {Array<Object>} filter_data.block_list The initial list of blocks to filter.
|
|
16
|
+
* @property {Object} [filter_data.empty_space] The candidate empty space being evaluated.
|
|
17
|
+
* @property {Set<Object>} filter_data.spaces_to_avoid A set to record spaces that become invalid.
|
|
18
|
+
* @property {Set<Object>} filter_data.no_fillable_space_set A set to record spaces that could not be filled.
|
|
19
|
+
*
|
|
20
|
+
* @returns {Array<Object>} The final, filtered list of blocks.
|
|
21
|
+
* @throws {Invalid_Space_To_Allocate_Exception} Thrown if no blocks remain after applying all filters.
|
|
22
|
+
*/
|
|
23
|
+
module.exports = function run_filters(filter_list, filter_data)
|
|
24
|
+
{
|
|
25
|
+
let block_list = filter_data.block_list
|
|
26
|
+
|
|
27
|
+
for (const filter of filter_list)
|
|
28
|
+
{
|
|
29
|
+
filter_data.block_list = block_list
|
|
30
|
+
block_list = filter.run(filter_data)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (block_list.length === 0)
|
|
34
|
+
{
|
|
35
|
+
if (filter_data.empty_space)
|
|
36
|
+
{
|
|
37
|
+
filter_data.spaces_to_avoid.add(filter_data.empty_space)
|
|
38
|
+
filter_data.no_fillable_space_set.add(filter_data.empty_space)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
logger.warn('no blocks left after filtering for the chosen space.')
|
|
42
|
+
throw new Invalid_Space_To_Allocate_Exception()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return block_list
|
|
46
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { slot_list_has_overlapped_slots } = require('../../../input_preparation/block_formatter/overlapped_slots')
|
|
2
|
+
|
|
3
|
+
module.exports = class Block_With_Overlapped_Slots_Filter
|
|
4
|
+
{
|
|
5
|
+
static run(filter_data)
|
|
6
|
+
{
|
|
7
|
+
return filter_data.block_list.filter(block => !this.#does_block_have_overlapped_slots(block))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static #does_block_have_overlapped_slots(block)
|
|
11
|
+
{
|
|
12
|
+
return slot_list_has_overlapped_slots(block.get_slot_list())
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const Insuficient_Items_Filter = require('../pre_selection_filter/Insuficient_Items_Filter')
|
|
2
|
+
const Block_With_Overlapped_Slots_Filter = require('./Block_With_Overlapped_Slots_Filter')
|
|
3
|
+
const Cargo_Profile = require('../../../models/Cargo_Profile')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Initial block filters. Overlapped-slot rejection is opt-in (prod default off).
|
|
7
|
+
* @returns {Array<{ run: Function }>}
|
|
8
|
+
*/
|
|
9
|
+
function build_initial_blocks_filter_list()
|
|
10
|
+
{
|
|
11
|
+
const filter_list = [Insuficient_Items_Filter]
|
|
12
|
+
if (Cargo_Profile.reject_blocks_with_overlapped_slots())
|
|
13
|
+
{
|
|
14
|
+
filter_list.push(Block_With_Overlapped_Slots_Filter)
|
|
15
|
+
}
|
|
16
|
+
return filter_list
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = build_initial_blocks_filter_list
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const math = require('@jetta/number-compare')
|
|
2
|
+
|
|
3
|
+
module.exports = class Blocks_Bigger_Than_Space_Filter extends require('../Block_Filter_Interface')
|
|
4
|
+
{
|
|
5
|
+
static run(filter_data)
|
|
6
|
+
{
|
|
7
|
+
return filter_data.block_list.filter(block => this.#is_block_smaller_than_empty_space(block, filter_data.empty_space))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static #is_block_smaller_than_empty_space(block, empty_space)
|
|
11
|
+
{
|
|
12
|
+
const height_fit = math.le(block.get_height(), empty_space.get_height())
|
|
13
|
+
const length_fit = math.le(block.get_length(), empty_space.get_length())
|
|
14
|
+
const width_fit = math.le(block.get_width(), empty_space.get_width())
|
|
15
|
+
return height_fit && length_fit && width_fit
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const Blocks_Bigger_Than_Space_Filter = require('./Blocks_Bigger_Than_Space_Filter')
|
|
2
|
+
const Tie_Ratio_Orientation_Filter = require('../../../Allocation_Optimization/tie_ratio/Tie_Ratio_Orientation_Filter')
|
|
3
|
+
const Tie_Ratio_Vertical_Stack_Filter = require('../../../Allocation_Optimization/tie_ratio/Tie_Ratio_Vertical_Stack_Filter')
|
|
4
|
+
|
|
5
|
+
module.exports = [
|
|
6
|
+
Blocks_Bigger_Than_Space_Filter,
|
|
7
|
+
Tie_Ratio_Orientation_Filter,
|
|
8
|
+
Tie_Ratio_Vertical_Stack_Filter
|
|
9
|
+
]
|
package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Insuficient_Items_Filter.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
const { cube_map_function } = require('../../../Blocks_Preparation/Cube_Map_Function')
|
|
2
|
+
|
|
3
|
+
module.exports = class Insuficient_Items_Filter
|
|
4
|
+
{
|
|
5
|
+
static #scratch_available_shapes = new Map()
|
|
6
|
+
|
|
7
|
+
static run(filter_data)
|
|
8
|
+
{
|
|
9
|
+
const available_shapes_map = this.#get_available_shapes_map(filter_data.item_list)
|
|
10
|
+
return filter_data.block_list.filter(
|
|
11
|
+
block => this.#has_sufficient_items(block, available_shapes_map)
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static #has_sufficient_items(block, available_shapes_map)
|
|
16
|
+
{
|
|
17
|
+
const required_shapes_map = this.#get_required_shapes_map(block)
|
|
18
|
+
if (required_shapes_map.size === 0)
|
|
19
|
+
{
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const scratch_map = this.#scratch_available_shapes
|
|
24
|
+
this.#copy_map_into_scratch(available_shapes_map, scratch_map)
|
|
25
|
+
|
|
26
|
+
for (const [shape_hash, required_amount] of required_shapes_map.entries())
|
|
27
|
+
{
|
|
28
|
+
const available_amount = scratch_map.get(shape_hash) || 0
|
|
29
|
+
if (available_amount < required_amount)
|
|
30
|
+
{
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
scratch_map.set(shape_hash, available_amount - required_amount)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static #copy_map_into_scratch(source_map, target_map)
|
|
40
|
+
{
|
|
41
|
+
target_map.clear()
|
|
42
|
+
for (const [shape_hash, amount] of source_map.entries())
|
|
43
|
+
{
|
|
44
|
+
target_map.set(shape_hash, amount)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static #get_required_shapes_map(block)
|
|
49
|
+
{
|
|
50
|
+
const required_shapes = new Map()
|
|
51
|
+
const slot_list = block.get_slot_list()
|
|
52
|
+
|
|
53
|
+
for (const slot of slot_list)
|
|
54
|
+
{
|
|
55
|
+
const shape_hash = cube_map_function(slot)
|
|
56
|
+
required_shapes.set(shape_hash, (required_shapes.get(shape_hash) || 0) + 1)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return required_shapes
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static #get_available_shapes_map(item_list)
|
|
63
|
+
{
|
|
64
|
+
const available_shapes = new Map()
|
|
65
|
+
|
|
66
|
+
for (const item of item_list)
|
|
67
|
+
{
|
|
68
|
+
const unique_shape_hashes = new Set()
|
|
69
|
+
for (const rotated_item of item.get_all_rotated_options())
|
|
70
|
+
{
|
|
71
|
+
unique_shape_hashes.add(cube_map_function(rotated_item))
|
|
72
|
+
}
|
|
73
|
+
const item_amount = item.get_amount()
|
|
74
|
+
for (const shape_hash of unique_shape_hashes)
|
|
75
|
+
{
|
|
76
|
+
available_shapes.set(shape_hash, (available_shapes.get(shape_hash) || 0) + item_amount)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return available_shapes
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/space_and_block_chooser/blocks_filters/pre_selection_filter/Pre_Selection_Filter_List.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const Insuficient_Items_Filter = require('./Insuficient_Items_Filter')
|
|
2
|
+
const Blocks_Lower_Than_Max_Tower_Height = require('./max_tower_height/Blocks_Lower_Than_Max_Tower_Height')
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = [
|
|
6
|
+
Insuficient_Items_Filter,
|
|
7
|
+
Blocks_Lower_Than_Max_Tower_Height
|
|
8
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const calculate_max_tower_height = require('./Max_Tower_Height')
|
|
2
|
+
const Config = require('../../../../models/Cargo_Profile')
|
|
3
|
+
const number_compare = require('@jetta/number-compare')
|
|
4
|
+
const Block_Filter_Interface = require('../../Block_Filter_Interface')
|
|
5
|
+
|
|
6
|
+
module.exports = class Blocks_Lower_Than_Max_Tower_Height extends Block_Filter_Interface
|
|
7
|
+
{
|
|
8
|
+
static run(filter_data)
|
|
9
|
+
{
|
|
10
|
+
if (!Config.enable_max_tower_cut())
|
|
11
|
+
{
|
|
12
|
+
return filter_data.block_list
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const max_height = calculate_max_tower_height(filter_data.container, filter_data.item_list)
|
|
16
|
+
return filter_data.block_list.filter(block => this.#is_block_smaller_than_max_height(block, max_height))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static #is_block_smaller_than_max_height(block, max_height)
|
|
20
|
+
{
|
|
21
|
+
return number_compare.le(block.get_height(), max_height)
|
|
22
|
+
}
|
|
23
|
+
}
|