private function equaliseWeight(PackedBox &$boxA, PackedBox &$boxB, float $targetWeight): bool
    {
        $anyIterationSuccessful = false;

        if ($boxA->getWeight() > $boxB->getWeight()) {
            $overWeightBox = $boxA;
            $underWeightBox = $boxB;
        } else {
            $overWeightBox = $boxB;
            $underWeightBox = $boxA;
        }

        $overWeightBoxItems = $overWeightBox->getItems()->asItemArray();
        $underWeightBoxItems = $underWeightBox->getItems()->asItemArray();

        foreach ($overWeightBoxItems as $key => $overWeightItem) {
            if ($overWeightItem->getWeight() + $boxB->getWeight() > $targetWeight) {
                continue; // moving this item would harm more than help
            }

            $newLighterBoxes = $this->doVolumeRepack(array_merge($underWeightBoxItems, [$overWeightItem]));
            if (count($newLighterBoxes) !== 1) {
                continue; //only want to move this item if it still fits in a single box
            }

            $underWeightBoxItems[] = $overWeightItem;

            if (count($overWeightBoxItems) === 1) { //sometimes a repack can be efficient enough to eliminate a box
                $boxB = $newLighterBoxes->top();
                $boxA = null;

                return true;
            } else {
                unset($overWeightBoxItems[$key]);
                $newHeavierBoxes = $this->doVolumeRepack($overWeightBoxItems);
                if (count($newHeavierBoxes) !== 1) {
                    continue;
                }

                if ($this->didRepackActuallyHelp($boxA, $boxB, $newHeavierBoxes->top(), $newLighterBoxes->top())) {
                    $boxB = $newLighterBoxes->top();
                    $boxA = $newHeavierBoxes->top();
                    $anyIterationSuccessful = true;
                }
            }
        }

        return $anyIterationSuccessful;
    }
private function equaliseWeight(PackedBox &$boxA, PackedBox &$boxB, float $targetWeight): bool
    {
        $anyIterationSuccessful = false;

        if ($boxA->getWeight() > $boxB->getWeight()) {
            $overWeightBox = $boxA;
            $underWeightBox = $boxB;
        } else {
            $overWeightBox = $boxB;
            $underWeightBox = $boxA;
        }

        $overWeightBoxItems = $overWeightBox->getItems()->asItemArray();
        $underWeightBoxItems = $underWeightBox->getItems()->asItemArray();

        foreach ($overWeightBoxItems as $key => $overWeightItem) {
            if ($overWeightItem->getWeight() + $boxB->getWeight() > $targetWeight) {
                continue; // moving this item would harm more than help
            }

            $newLighterBoxes = $this->doVolumeRepack(array_merge($underWeightBoxItems, [$overWeightItem]));
            if (count($newLighterBoxes) !== 1) {
                continue; //only want to move this item if it still fits in a single box
            }

            $underWeightBoxItems[] = $overWeightItem;

            if (count($overWeightBoxItems) === 1) { //sometimes a repack can be efficient enough to eliminate a box
                $boxB = $newLighterBoxes->top();
                $boxA = null;

                return true;
            } else {
                unset($overWeightBoxItems[$key]);
                $newHeavierBoxes = $this->doVolumeRepack($overWeightBoxItems);
                if (count($newHeavierBoxes) !== 1) {
                    continue;
                }

                if ($this->didRepackActuallyHelp($boxA, $boxB, $newHeavierBoxes->top(), $newLighterBoxes->top())) {
                    $boxB = $newLighterBoxes->top();
                    $boxA = $newHeavierBoxes->top();
                    $anyIterationSuccessful = true;
                }
            }
        }

        return $anyIterationSuccessful;
    }
private function equaliseWeight ( PackedBox & $ boxA , PackedBox & $ boxB , float $ targetWeight ) : bool { $ anyIterationSuccessful = false ; if ( $ boxA -> getWeight ( ) > $ boxB -> getWeight ( ) ) { $ overWeightBox = $ boxA ; $ underWeightBox = $ boxB ; } else { $ overWeightBox = $ boxB ; $ underWeightBox = $ boxA ; } $ overWeightBoxItems = $ overWeightBox -> getItems ( ) -> asItemArray ( ) ; $ underWeightBoxItems = $ underWeightBox -> getItems ( ) -> asItemArray ( ) ; foreach ( $ overWeightBoxItems as $ key => $ overWeightItem ) { if ( $ overWeightItem -> getWeight ( ) + $ boxB -> getWeight ( ) > $ targetWeight ) { continue ; // moving this item would harm more than help } $ newLighterBoxes = $ this -> doVolumeRepack ( array_merge ( $ underWeightBoxItems , [ $ overWeightItem ] ) ) ; if ( count ( $ newLighterBoxes ) !== 1 ) { continue ; //only want to move this item if it still fits in a single box } $ underWeightBoxItems [ ] = $ overWeightItem ; if ( count ( $ overWeightBoxItems ) === 1 ) { //sometimes a repack can be efficient enough to eliminate a box $ boxB = $ newLighterBoxes -> top ( ) ; $ boxA = null ; return true ; } else { unset ( $ overWeightBoxItems [ $ key ] ) ; $ newHeavierBoxes = $ this -> doVolumeRepack ( $ overWeightBoxItems ) ; if ( count ( $ newHeavierBoxes ) !== 1 ) { continue ; } if ( $ this -> didRepackActuallyHelp ( $ boxA , $ boxB , $ newHeavierBoxes -> top ( ) , $ newLighterBoxes -> top ( ) ) ) { $ boxB = $ newLighterBoxes -> top ( ) ; $ boxA = $ newHeavierBoxes -> top ( ) ; $ anyIterationSuccessful = true ; } } } return $ anyIterationSuccessful ; }
Attempt to equalise weight distribution between 2 boxes.

@param PackedBox $boxA
@param PackedBox $boxB
@param float     $targetWeight

@return bool was the weight rebalanced?
Attempt to equalise weight distribution between 2 boxes .