/** * Get pick up date time from a driving mission, which may or may not be * assigned to a working day or shift. * * @param DrivingMission $drivingMission * @return \DateTime local time */ private function getPickUpDateTime(DrivingMission $drivingMission) { /** @var DateTimeService $timeService */ $timeService = $this->container->get('tixi_api.datetimeservice'); /** @var DrivingOrder $drivingOrder */ $drivingOrder = $drivingMission->getDrivingOrders()[0]; $pickUpDate = $timeService->convertToLocalDateTime($drivingOrder->getPickUpDate()); $localMinutes = $drivingMission->getServiceMinuteOfDay(); $localHours = intval($localMinutes / 60); $localMinutes = $localMinutes - $localHours * 60; $pickUpDate->setTime($localHours, $localMinutes); return $pickUpDate; }
/** * @param DrivingOrder $drivingOrder * @return mixed|void */ public function handleNewDrivingOrder(DrivingOrder $drivingOrder) { /** @var DrivingOrderRepository $drivingOrderRepository */ $drivingOrderRepository = $this->container->get('drivingorder_repository'); /** @var DrivingMissionRepository $drivingMissionRepository */ $drivingMissionRepository = $this->container->get('drivingmission_repository'); /** @var DateTimeService $timeService */ $timeService = $this->container->get('tixi_api.datetimeservice'); $pickUpTime = $drivingOrder->getPickUpTime(); if ($pickUpTime->getTimezone()->getName() === 'UTC') { $drivingOrder->setPickUpTime($timeService->convertToLocalDateTime($pickUpTime)); } $drivingMission = DrivingMission::registerDrivingMissionFromOrder($drivingOrder); $drivingMissionRepository->store($drivingMission); $drivingOrderRepository->store($drivingOrder); }
/** * generates identically hash for this node only (adjacenceMatrix) * @return string */ public function getRideNodeHashId() { return hash('md4', $this->startAddress->getHashFromBigIntCoordinates() . $this->targetAddress->getHashFromBigIntCoordinates() . $this->startMinute . $this->endMinute . $this->drivingMission->getId()); }
/** * If mission is possible, assign the driving mission to the driving pool. * * Special: * The driving mission is assigned to the pool where it starts. * Long distance sets all relevant driving pools to manuallyEdited=true, * Conditions: * 1. vehicle has pool(s) assigned for the duration of the ride * 2. Same driver (or none) in all pool(s). * 3. Long distance ride ends before before 0100 next day. * See also: $this->getDrivingPools() * Otherwise return an error message. * * @param DrivingMission $drivingMission * @param DrivingPool $drivingPool * @param array $errors * @return boolean */ private function assignDrivingMissionToPool(DrivingMission $drivingMission, DrivingPool $drivingPool, &$errors) { if (null !== $drivingMission && null !== $drivingPool) { if (null !== $drivingMission->getDrivingPool()) { $this->removeDrivingMissionFromPool($drivingMission, $errors); } /* FIRST: assign the owning side of the ManyToOne association */ $drivingMission->assignDrivingPool($drivingPool); /* SECOND: assign the inverse side of the ManyToOne association */ $drivingPool->assignDrivingMission($drivingMission); return true; } return false; }
/** * @param DrivingOrder $drivingOrder * @return DrivingMission */ public static function registerDrivingMissionFromOrder(DrivingOrder $drivingOrder) { $drivingMission = new DrivingMission(); $drivingMission->setDirection(self::SAME_START); $drivingMission->setServiceOrder(array($drivingOrder->getId())); $boardingTime = DispositionVariables::getBoardingTimes(); $extraMinutesPassenger = $drivingOrder->getPassenger()->getExtraMinutes(); $additionalTimesOnRide = $boardingTime + $extraMinutesPassenger; $serviceMinuteOfDay = DateTimeService::getMinutesOfDay($drivingOrder->getPickUpTime()); $serviceDuration = $drivingOrder->getRoute()->getDurationInMinutes() + $additionalTimesOnRide; $serviceDistance = $drivingOrder->getRoute()->getDistanceInMeters(); $drivingMission->setServiceMinuteOfDay($serviceMinuteOfDay); $drivingMission->setServiceDuration($serviceDuration); $drivingMission->setServiceDistance($serviceDistance); //DrivingMission <-> Order $drivingMission->assignDrivingOrder($drivingOrder); $drivingOrder->assignDrivingMission($drivingMission); return $drivingMission; }
/** * creates an array with RideNodes according to a drivingMission * with missionId as arrayKey * * @param DrivingMission $drivingMission * @return RideNode */ public function createRideNodeFromDrivingMission(DrivingMission $drivingMission) { /** * if DrivingMission got no elements in ServiceOrder => singleOrder * if elements exist => multiOrder */ if (empty($drivingMission->getServiceOrder())) { /**@var $order DrivingOrder */ $order = $drivingMission->getDrivingOrders()->first(); $startAddress = $order->getRoute()->getStartAddress(); $targetAddress = $order->getRoute()->getTargetAddress(); } else { $sort = $drivingMission->getServiceOrder(); $first = reset($sort); $last = count($sort); /**@var $firstOrder DrivingOrder */ $firstOrder = $drivingMission->getDrivingOrders()->get($sort[$first]); /**@var $lastOrder DrivingOrder */ $lastOrder = $drivingMission->getDrivingOrders()->get($sort[$last]); if ($drivingMission->getDirection() === DrivingMission::SAME_START) { $startAddress = $firstOrder->getRoute()->getStartAddress(); $targetAddress = $lastOrder->getRoute()->getTargetAddress(); } else { $startAddress = $firstOrder->getRoute()->getStartAddress(); $targetAddress = $firstOrder->getRoute()->getTargetAddress(); } } return RideNode::registerPassengerRide($drivingMission, $startAddress, $targetAddress); }
/** * @param InputInterface $input * @param OutputInterface $output * @return int|null|void */ public function execute(InputInterface $input, OutputInterface $output) { $output->writeln('building variables...'); $month = $input->getArgument('month'); if (!$month) { $month = 1; } $em = $this->getContainer()->get('entity_manager'); $workingMonthRepo = $this->getContainer()->get('workingmonth_repository'); $workingDayRepo = $this->getContainer()->get('workingday_repository'); $shiftRepo = $this->getContainer()->get('shift_repository'); $shiftTypeRepo = $this->getContainer()->get('shifttype_repository'); $drivingPoolRepo = $this->getContainer()->get('drivingpool_repository'); $passengerRepo = $this->getContainer()->get('passenger_repository'); $driverRepo = $this->getContainer()->get('driver_repository'); $vehicleRepo = $this->getContainer()->get('vehicle_repository'); $addressRepo = $this->getContainer()->get('address_repository'); $poiRepo = $this->getContainer()->get('poi_repository'); $routeRepo = $this->getContainer()->get('route_repository'); $drivingMissionRepo = $this->getContainer()->get('drivingmission_repository'); $drivingOrderRepo = $this->getContainer()->get('drivingorder_repository'); $repeatedDrivingAssertionRepo = $this->getContainer()->get('repeateddrivingassertion_repository'); $repeatedDrivingAssertionPlanRepo = $this->getContainer()->get('repeateddrivingassertionplan_repository'); $repeatedDrivingOrderRepo = $this->getContainer()->get('repeateddrivingorder_repository.doctrine'); $repeatedDrivingOrderPlanRepo = $this->getContainer()->get('repeateddrivingorderplan_repository.doctrine'); $time = $this->getContainer()->get('tixi_api.datetimeservice'); $routingMachine = $this->getContainer()->get('tixi_app.routingmachine'); $routeManagement = $this->getContainer()->get('tixi_app.routemanagement'); $dispoManagement = $this->getContainer()->get('tixi_app.dispomanagement'); $this->zonePlanRepository = $this->getContainer()->get('zoneplan_repository'); $this->zoneRepository = $this->getContainer()->get('zone_repository'); $monthDate = new \DateTime('today'); $monthDate->modify('+' . $month . ' month'); // depreciated: $monthDate->modify('+ 10 year'); $monthDate->modify('first day of this month'); $shiftTypes = $shiftTypeRepo->findAllActive(); $output->writeln('target date is ' . $monthDate->format('d.m.Y')); $output->writeln('building driver assertion plans...'); $drivers = $driverRepo->findAllActive(); foreach ($drivers as $driver) { //no other assertion for zivis if ($driver->getDriverCategory()->getId() == 2) { continue; } $reDrivingAssertionPlan = RepeatedDrivingAssertionPlan::registerRepeatedAssertionPlan('test', new \DateTime('today'), 'weekly', rand(0, 1)); $reDrivingAssertionPlan->assignDriver($driver); $driver->assignRepeatedDrivingAssertionPlan($reDrivingAssertionPlan); $repeatedDrivingAssertionPlanRepo->store($reDrivingAssertionPlan); for ($i = 1; $i <= 7; $i++) { if (rand(0, 3) < 3) { $reDrivingWeeklyAssertion = new RepeatedWeeklyDrivingAssertion(); $reDrivingWeeklyAssertion->addShiftType($shiftTypes[rand(0, count($shiftTypes) - 1)]); $reDrivingWeeklyAssertion->addShiftType($shiftTypes[rand(0, count($shiftTypes) - 1)]); $reDrivingWeeklyAssertion->addShiftType($shiftTypes[rand(0, count($shiftTypes) - 1)]); $reDrivingWeeklyAssertion->setWeekday($i); $reDrivingWeeklyAssertion->setAssertionPlan($reDrivingAssertionPlan); $reDrivingAssertionPlan->assignRepeatedDrivingAssertion($reDrivingWeeklyAssertion); $repeatedDrivingAssertionRepo->store($reDrivingWeeklyAssertion); } } } $em->flush(); $output->writeln('building driving pools...'); $drivingPools = 0; $workingMonth = $workingMonthRepo->findWorkingMonthByDate($monthDate); if ($workingMonth !== null) { $output->writeln("WorkingMonth " . $monthDate->format('m') . " already exists"); } else { $workingMonth = $dispoManagement->openWorkingMonth($monthDate->format('Y'), $monthDate->format('m')); $workingDays = $workingMonth->getWorkingDays(); //create workingDays shifts, assign them drivingpools, get amount of needed drivers /** @var $workingDay WorkingDay */ foreach ($workingDays as $workingDay) { /** @var $shiftType ShiftType */ foreach ($workingDay->getShifts() as $shift) { $shift->setAmountOfDrivers(rand(12, 18)); for ($i = 1; $i <= $shift->getAmountOfDrivers(); $i++) { $drivingPool = DrivingPool::registerDrivingPool($shift); $shift->assignDrivingPool($drivingPool); $drivingPoolRepo->store($drivingPool); $drivingPools++; } } } } $em->flush(); $output->writeln('building unclassified zone...'); $this->unclassifiedZone = $this->getUnclassifiedZone(); if (is_null($this->unclassifiedZone)) { $output->writeln('error: cannot create unclassified zone!'); } $output->writeln('building driving orders...'); /**@var $pois POI[] */ $pois = $poiRepo->findAll(); $countPois = count($pois); $orders = array(); $routes = array(); //create Driving Orders $countOrders = 0; foreach ($shiftTypes as $shiftType) { $approxOrdersPerShift = rand(40, 60); for ($i = 0; $i < $approxOrdersPerShift; $i++) { /**@var $passenger Passenger */ $passenger = $passengerRepo->find(rand(100, 500)); $passenger->setIsInWheelChair(rand(0, 1)); /** WARNING: saving times in UTC on database, but minutesOfDay are from midnight, causing * wrong data if a time is UTC 23:30 but CET 00:30 (= 30 minutesOfDay) */ $stStart = $time->convertToLocalDateTime($shiftType->getStart()); $stEnd = $time->convertToLocalDateTime($shiftType->getEnd()); $stDuration = $stStart->diff($stEnd); $minutes = $stDuration->h * 60 + $stDuration->i; $pickupTime = clone $stStart; $pickupTime->add(new \DateInterval('PT' . rand(1, $minutes) . 'M')); $order = DrivingOrder::registerDrivingOrder($passenger, $monthDate, $pickupTime, rand(0, 1), null, 0, 0, 1); $start = $passenger->getAddress(); $target = $pois[rand(0, $countPois - 1)]->getAddress(); $route = Route::registerRoute($start, $target); $hashKey = hash('crc32', $start->getHashFromBigIntCoordinates() . $target->getHashFromBigIntCoordinates()); $routes[$hashKey] = $route; $route = $routeRepo->storeRouteIfNotExist($route); $order->assignRoute($route); $order->assignPassenger($passenger); $passenger->assignDrivingOrder($order); $drivingOrderRepo->store($order); array_push($orders, $order); } } $output->writeln('building driving missions and routes...'); $routingMachine->fillRoutingInformationForMultipleRoutes($routes); /**@var $order DrivingOrder */ foreach ($orders as $order) { $passenger = $order->getPassenger(); $route = $order->getRoute(); $boardingTime = DispositionVariables::BOARDING_TIME + DispositionVariables::DEBOARDING_TIME; $extraMinutesPassenger = $passenger->getExtraMinutes(); $additionalTimesOnRide = $boardingTime + $extraMinutesPassenger; $serviceMinuteOfDay = $time->getMinutesOfDay($order->getPickUpTime()); $serviceDuration = $route->getDurationInMinutes() + $additionalTimesOnRide; $serviceDistance = $route->getDistanceInMeters(); //DrivingMission <-> DrivingOrder $drivingMission = DrivingMission::registerDrivingMission(rand(0, 1), $serviceMinuteOfDay, $serviceDuration, $serviceDistance); $drivingMission->assignDrivingOrder($order); $order->assignDrivingMission($drivingMission); $drivingMissionRepo->store($drivingMission); // DrivingOrder <-> Zone $cities = array($route->getStartAddress()->getCity(), $route->getTargetAddress()->getCity()); $zone = $this->getZoneWithHighestPriorityForCities($cities); $order->assignZone($zone); $countOrders++; } $em->flush(); $output->writeln("\n--------------------------------------------\n" . "Testdata created for month: " . $monthDate->format('m.Y') . " with:\n" . $drivingPools . " DrivingPools \n" . "And orders for one day: " . $monthDate->format('d.m.Y') . " with:\n" . $countOrders . " DrivingOrders and Routes \n"); }