public function canLoadObserver($event)
 {
     if (!($current_tuple = $event->getPointSequence())) {
         throw new Exception('Event ' . $event->getName() . 'does not have "point_sequence" param!');
     }
     if (!($candidate = $event->getPoint())) {
         throw new Exception('Event ' . $event->getName() . 'does not have "point_sequence" param!');
     }
     $pointSequence = array_merge(Helper::getPointSequenceFromTuple($current_tuple), [$candidate]);
     $checkLoading = $this->getPrecise() == 100 ? false : rand(0, 100) < $this->getData('check_transitional_loading_probability') && $this->_lastPointIsPickup($pointSequence);
     // if needed, check 3D constraints
     $event->getResultContainer()->result = $checkLoading ? $this->canLoad($pointSequence) : true;
 }
 protected function _generateNestedPointSequences($node)
 {
     $pointSequence = $node->getContent()->getPoints();
     $generator = new Generator(['tuple_length' => Point::getPointCount($this->getPoints()), 'generating_elements' => Helper::getGeneratorDataFromPoints($this->getPoints()), 'current_path' => $node->getContent(), 'weight_capacity' => $this->getWeightCapacity(), 'load_area' => $this->getLoadArea()]);
     // $generator->validate();
     $points = Helper::getGeneratorDataFromPoints($pointSequence);
     $result = Helper::getPointSequencesFromGeneratorData($generator->generateNextObjects($points));
     if ($result) {
         // hack: if all PDP points except of depot are present, add depot
         $nodeHasAllPointsExceptOfDepot = Helper::pointSequenceIncludesAllPickupsAndDeliveries(reset($result), $this->getPoints());
         if ($nodeHasAllPointsExceptOfDepot) {
             foreach ($result as &$resultPointSequence) {
                 $resultPointSequence = array_merge($resultPointSequence, [$this->getDepot()]);
             }
         }
     }
     return $result;
 }
 protected function _getSuccessiveElements($tuple)
 {
     $result = [];
     // we assume that tuple contain \Litvinenko\Combinatorics\Pdp\Point objects
     $currentPath = $this->_getCurrentPath($tuple);
     foreach ($this->getGeneratingElements() as $element) {
         $point = $element['value'];
         // if current path does not contain this point
         if (!$currentPath->doesContain($point)) {
             // add pickup point if whether vehicle can take box at this point
             if ($point->isPickup() && $currentPath->getCurrentWeight() + $point->getBoxWeight() <= $this->getWeightCapacity() && $currentPath->getCurrentVolume() + $point->getBoxVolume() <= Helper::getLoadAreaVolume($this->getLoadArea()) || $point->isDelivery() && $currentPath->doesContain($point->getPairId())) {
                 $resultContainer = new \stdClass();
                 // event observers will write info to this object
                 App::dispatchEvent('point_add_before', ['point' => $point, 'point_sequence' => $tuple, 'result_container' => $resultContainer]);
                 if (!isset($resultContainer->result) || isset($resultContainer->result) && $resultContainer->result !== false) {
                     $result[] = $element;
                 }
             }
         }
     }
     return $result;
 }