/**
  * Create DTO for the selected working month
  * @param WorkingMonth $workingMonth
  * @return array
  */
 public function workingMonthToEditDTO(WorkingMonth $workingMonth)
 {
     $tr = $this->container->get('translator');
     $dto = new MonthlyPlanGetDTO();
     $dto->targetSrc = $this->container->get('router')->generate('tixiapi_dispo_monthlyplan_edit', array('workingMonthId' => $workingMonth->getId(), 'workingDayId' => '__workingDayId__', 'editParams' => 'edit'));
     $dto->closeUrl = $this->container->get('router')->generate('tixiapi_dispo_monthlyplans_get');
     /** @var WorkingDay $workingDay */
     foreach ($workingMonth->getWorkingDays() as $workingDay) {
         $dayDto = new MonthlyPlanGetDayDTO();
         $dayDto->workingDayId = $workingDay->getId();
         $dayDto->swissDate = $workingDay->getDate()->format('d.m.Y');
         $dayDto->dayOfWeek = $tr->trans(DateTimeService::getDayOfWeek($workingDay->getDate()));
         $shifts = $workingDay->getShifts();
         /** @var Shift $shift */
         foreach ($shifts as $shift) {
             $dayDto->shifts[] = $this->getMonthlyPlanGetShiftDTO($shift);
         }
         $dto->workingDays[] = $dayDto;
     }
     /** @var Shift $shift */
     foreach ($workingMonth->getWorkingDays()[0]->getShifts() as $shift) {
         $dto->shiftNames[] = $shift->getShiftType()->getName();
     }
     return $dto;
 }
 /**
  * Production code:
  * runs routing algorithm to set optimized missions and orders for a shift
  *
  * @param Shift $shift
  * @param boolean $verbose
  * @return array containing information for user
  */
 public function buildRidePlanForShift(Shift $shift, $verbose = true)
 {
     $day = $shift->getDate();
     $tr = $this->container->get('translator');
     $infos = array();
     if ($verbose) {
         $infos[] = $tr->trans('ride.info.shift') . ' ' . $day->format('d.m.Y') . ', ' . $tr->trans(DateTimeService::getDayOfWeek($day)) . ' ' . $shift->getShiftType()->getName() . '.';
     }
     //set php execution timeout for big calculations
     ini_set('max_execution_time', 300);
     $em = $this->container->get('entity_manager');
     $em->beginTransaction();
     //set STRATEGY for RideOptimization
     $rideStrategy = new RideStrategyAnnealing();
     $rideStrategy->setContainer($this->container);
     //set Shift
     $shift->setManuallyEdited(false);
     // optimization resets manual attribute
     // set DrivingPools
     $drivingPools = $shift->getDrivingPoolsAsArray();
     if (count($drivingPools) < 1) {
         $em->rollback();
         $infos[] = $tr->trans('ride.error.noPools') . ' ' . $shift->getShiftType()->getName() . '.';
         return $infos;
     }
     // set DrivingMissions
     $dispoManagement = $this->container->get('tixi_app.dispomanagement');
     $drivingMissions = $dispoManagement->getDrivingMissionsInShift($shift);
     if (count($drivingMissions) < 1) {
         $em->rollback();
         $infos[] = $tr->trans('ride.error.noMissions') . ' ' . $shift->getShiftType()->getName() . '.';
         return $infos;
     }
     //clean drivingPools for new optimization
     foreach ($drivingPools as $pool) {
         $pool->removeDrivingMissions();
     }
     $configurationBuilder = new ConfigurationBuilder($drivingMissions, $drivingPools, $rideStrategy);
     $this->logger($tr->trans('ride.log.dayAndShift'), array($day->format('d.m.Y'), $shift->getShiftType()->getName()));
     //get all empty Rides
     $emptyRides = $configurationBuilder->buildAllPossibleEmptyRides();
     //get routing information from routing machine and fill node objects
     $s = microtime(true);
     $routeManagement = $this->container->get('tixi_app.routemanagement');
     $emptyRides = $routeManagement->fillRoutesForMultipleRideNodes($emptyRides);
     $e = microtime(true);
     $this->logger($tr->trans('ride.log.routingTime'), array(count($emptyRides), round($e - $s, 3)));
     //create ride configurations with strategy
     $s = microtime(true);
     $rideConfigurations = $configurationBuilder->buildConfigurations();
     if ($rideConfigurations === null) {
         $em->rollback();
         $infos[] = $tr->trans('ride.error.noConfiguration');
         return $infos;
     }
     $e = microtime(true);
     $nodes = count($rideConfigurations);
     $this->logger($tr->trans('ride.log.buildTime'), array($nodes, round($e - $s, 3)));
     // get the best feasible configuration
     $rideConfiguration = $this->getBestConfiguration($rideConfigurations);
     $configurationAnalyzer = new ConfigurationAnalyzer($rideConfiguration);
     $configurationAnalyzer->assignMissionsAndVehiclesToPool();
     $booked = $rideConfiguration->countNodes();
     $overbooked = count($rideConfiguration->getNotFeasibleNodes());
     if ($verbose) {
         $infos[] = $tr->trans('ride.info.nodes') . ' ' . $booked . ', ' . $tr->trans('ride.info.overbooked') . ' ' . $overbooked . '.';
     }
     $this->logger($tr->trans('ride.log.success'), array($nodes, $overbooked));
     // if everything worked, return successfully
     $em->commit();
     $em->flush();
     return $infos;
 }
 /**
  * @param \DateTime $date
  * @return string
  */
 private function dateToLocalWeekday(\DateTime $date)
 {
     $weekday = DateTimeService::getDayOfWeek($date);
     $tr = $this->get('translator');
     return $tr->trans($weekday);
 }
 /**
  * Assign drivers, vehicles and driving orders (missions) to driving pools.
  *
  * @param \DateTime $scope is the date of the WorkingDay being assigned
  * @return mixed value true = success
  */
 protected function assignResourcesForDay(\DateTime $scope)
 {
     set_time_limit(60);
     $timeStamp = microtime(true);
     $tr = $this->get('translator');
     $logger = $this->get('logger');
     $memo = '';
     /** @var DrivingAssertionManagement $drivingAssertionService */
     $drivingAssertionService = $this->get('tixi_app.drivingassertionmanagement');
     /** @var DispositionManagement $dispoService */
     $dispoService = $this->get('tixi_app.dispomanagement');
     /** @var EntityManager $entityManager */
     $entityManager = $this->get('entity_manager');
     /** @var WorkingDayRepository $workingDayRepository */
     $workingDayRepository = $this->get('workingday_repository');
     $workingDay = $workingDayRepository->findWorkingDayByDate($scope);
     if (null !== $workingDay) {
         /* add driving assertions for working day ----------------------- */
         $logger->debug($tr->trans('productionplan.debug.addDrivingAssertions') . ' ' . $scope->format('d.m.Y'));
         $errors = $drivingAssertionService->createAllDrivingAssertionsForNewWorkingDay($workingDay);
         foreach ($errors as $error) {
             $memo .= $error . "\n";
         }
         $entityManager->flush();
         // update MySQL database
         $entityManager->clear();
         // clear ORM cache
         /* assign driving assertions to driving pools ------------------- */
         $logger->debug($tr->trans('productionplan.debug.assignAssertions') . ' ' . $scope->format('d.m.Y'));
         $workingDayChildren = $workingDayRepository->fetchWorkingDayChildrenForDay($scope);
         $errors = $dispoService->assignAssertionsToPools($workingDayChildren);
         foreach ($errors as $error) {
             $memo .= $error . "\n";
         }
         $entityManager->flush();
         // update MySQL database ***ERROR HERE***
         $entityManager->clear();
         // clear ORM cache
         /* assign vehicles to driving pools ----------------------------- */
         $logger->debug($tr->trans('productionplan.debug.assignVehicles') . ' ' . $scope->format('d.m.Y'));
         $workingDayChildren = $workingDayRepository->fetchWorkingDayChildrenForDay($scope);
         $errors = $dispoService->assignVehiclesToPools($workingDayChildren);
         foreach ($errors as $error) {
             $memo .= $error . "\n";
         }
         $entityManager->flush();
         // update MySQL database
         $entityManager->clear();
         // clear ORM cache
         /* add driving orders for working day --------------------------- */
         $logger->debug($tr->trans('productionplan.debug.addDrivingOrders') . ' ' . $scope->format('d.m.Y'));
         /** @var DrivingOrderManagement $drivingOrderService */
         $drivingOrderService = $this->get('tixi_app.drivingordermanagement');
         $errors = $drivingOrderService->handleNewWorkingDay($workingDay, DrivingOrder::BOOKED);
         // status BOOKED
         foreach ($errors as $error) {
             $memo .= $error . "\n";
         }
         $entityManager->flush();
         // update MySQL database
         $entityManager->clear();
         // clear ORM cache
         /* build ride configurations ------------------------------------ */
         $logger->debug($tr->trans('productionplan.debug.assignOrders') . ' ' . $scope->format('d.m.Y'));
         /**@var RideManagement $rideManagement */
         $rideManagement = $this->get('tixi_app.ridemanagement');
         $workingDayChildren = $workingDayRepository->fetchWorkingDayChildrenForDay($scope);
         foreach ($workingDayChildren->getShifts() as $shift) {
             $errors = $rideManagement->buildRidePlanForShift($shift);
             foreach ($errors as $error) {
                 $memo .= $error . "\n";
             }
         }
     } else {
         $memo .= $tr->trans('productionplan.form.daymissing') . "\n";
     }
     $memo .= $tr->trans('productionplan.form.memo.days') . ' ' . $tr->trans(DateTimeService::getDayOfWeek($scope)) . ' ' . $scope->format('d.m.Y') . ' (' . $this->getTimeExpired($timeStamp) . "s).\n";
     $queueService = $this->get('tixi_app.queueservice');
     $queueService->push($this->getQueueTag($scope), $memo);
     return true;
     // success = true
 }