<?php
namespace App\Controller;
use App\Classes\oAddress;
use App\Entity\Addresse;
use App\Entity\AddressesList;
use App\Entity\Computing;
use App\Entity\Timing;
use App\Form\ComputingType;
use App\Geoloc\MapsGeolocService;
use App\Geoloc\DirectionsService;
use App\Repository\AddresseRepository;
use App\Repository\CityRepository;
use App\Repository\ComputingRepository;
use App\Repository\TimingRepository;
use App\Service\DataFormatService;
use App\Service\GeoLocService;
use Doctrine\ORM\EntityManagerInterface;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/computing")
*/
class ComputingController extends AbstractController
{
/**
* @Route("/", name="app_computing_index", methods={"GET"})
*/
public function index(ComputingRepository $computingRepository): Response
{
return $this->render('computing/index.html.twig', [
'computings' => $computingRepository->findAll(),
]);
}
/**
* @Route("/{id}/compute", name="app_computing_compute", methods={"GET"})
*/
public function compute(ComputingRepository $computingRepository, Computing $computing, TimingRepository $timingRepository): Response
{
// Etape 1 : Geocodage
if($computing->getLat() == null || $computing->getLon() == null ){
return $this->redirectToRoute('app_computing_geocode', ['id'=>$computing->getId()], Response::HTTP_SEE_OTHER);
}
$timingRepository->purgeComputingTiming($computing);
return $this->render('computing/bulk_compute.html.twig', [
'computing' => $computing
]);
}
/**
* @Route("/{id}/ajax_geocode/{limit}/{offset}", name="app_computing_ajax_geocode", methods={"GET"})
*/
public function ajax_geocode(ComputingRepository $computingRepository, Computing $computing, TimingRepository $timingRepository, AddresseRepository $addresseRepository , EntityManagerInterface $entityManager, int $limit, int $offset): Response
{
$output = [];
$output['continue'] = true;
$addressesGroup = $computing->getAddressesGroup();
$count = $addresseRepository->coundByAddressGroup($addressesGroup->getId());
if($offset + $limit > $count){
$output['continue'] = false;
}
$addresses = $addresseRepository->findByAddressGroup($addressesGroup->getId(), $limit, $offset);
$modes = array();
$modes[] = DirectionsService::MODE_DRIVING_LABEL;
$modes[] = DirectionsService::MODE_BICYCLING_LABEL;
$modes[] = DirectionsService::MODE_TRANSIT_LABEL;
$modes[] = DirectionsService::MODE_WALKING_LABEL;
// Departure time :
$optionalData = [];
$departureDate = $computing->getDepartureDateTime();
if($departureDate != NULL )
{
$optionalData['departure_time'] =$departureDate->getTimestamp();
}
foreach ($modes as $mode){
foreach ($addresses as $address){
// Timing aller
$timing = new Timing();
$timing->setDirection(Timing::DIRECTION_ALLER);
$timing->setAddressesList($addressesGroup);
$timing->setAddress($address);
$timing->setComputing($computing);
$timing->setEngine('googleAPI');
$timing->setTransportMode(DirectionsService::ConvertTransportModeToID($mode));
$timing->setStatus(Timing::STATUT_A_CALCULER);
$timingRepository->add($timing);
$timingRepository->computeTiming($timing, $mode, $optionalData);
/*
// Timing retour
$timing = new Timing();
$timing->setDirection(Timing::DIRECTION_RETOUR);
$timing->setAddressesList($addressesGroup);
$timing->setAddress($address);
$timing->setComputing($computing);
$timing->setEngine('googleAPI');
$timing->setTransportMode(DirectionsService::ConvertTransportModeToID($mode));
$timing->setStatus(Timing::STATUT_A_CALCULER);
$timingRepository->add($timing);
$timingRepository->computeTiming($timing, $mode);
*/
}
}
$entityManager->flush();
$output['percentage'] = round(($offset+$limit)/$count *100 , 0 );
if($output['percentage']>100) {$output['percentage'] = 100;}
return new JsonResponse($output);
}
/**
* @Route("/{id}/geocode", name="app_computing_geocode", methods={"GET", "POST"})
*/
public function geocode(Request $request, ComputingRepository $computingRepository , CityRepository $cityRepository, Computing $computing): Response
{
// $possibilites = GeoLocService::geolocAddress($computing->getAddresse());
$oAddresse = new oAddress();
$oAddresse->setAddress($computing->getAddresse());
$possibilites = GeoLocService::geolocAddress($oAddresse, $cityRepository);
if ($this->isCsrfTokenValid('geocode'.$computing->getId(), $request->request->get('_token'))) {
$geocodingChoice = $request->request->get('geocodingChoice');
$tmp = explode("||", $geocodingChoice);
$lat = $tmp[0];
$lon = $tmp[1];
$computing->setLat($lat);
$computing->setLon($lon);
$computing->setStatus(Computing::STATUT_GEO_VALIDE);
$computingRepository->add($computing);
return $this->redirectToRoute('app_computing_compute', ['id'=>$computing->getId()], Response::HTTP_SEE_OTHER);
}
return $this->render('computing/geocode.html.twig', [
'computing' => $computing,
'possibilites' => $possibilites
]);
}
/**
* @Route("/new", name="app_computing_new", methods={"GET", "POST"})
*/
public function new(Request $request, ComputingRepository $computingRepository): Response
{
$computing = new Computing();
$form = $this->createForm(ComputingType::class, $computing);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$computingRepository->add($computing);
return $this->redirectToRoute('app_computing_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('computing/new.html.twig', [
'computing' => $computing,
'form' => $form,
]);
}
/**
* @Route("/{id}", name="app_computing_show", methods={"GET"})
*/
public function show(Computing $computing, TimingRepository $timingRepository): Response
{
$outputTimings = [];
$moyennesData = [];
$addressesList = $computing->getAddressesGroup();
$addresses = $addressesList->getAddresses();
$transportModes = DirectionsService::GetTransportModes();
//$directions = ['aller' => Timing::DIRECTION_ALLER, 'retour' =>Timing::DIRECTION_RETOUR];
$directions = ['aller' => Timing::DIRECTION_ALLER];
foreach ($addresses as $address)
{
$tmp = [];
$tmp["address_name"] = $address->toString();
foreach ($transportModes as $transportMode)
{
$transportModeID = DirectionsService::ConvertTransportModeToID($transportMode);
foreach ($directions as $direction_label => $direction)
{
$timings = $timingRepository->findTimingsByComputingAddressAndTransportMode($computing, $address, $transportModeID, $direction);
if(isset($timings[0]))
{
$seconds = $timings[0]->getTime();
$tmp[$direction_label]["timing"][$transportMode] = DataFormatService::formatSecond($seconds);
$tmp[$direction_label]["distance"][$transportMode] = round($timings[0]->getDistance()/1000, 2)."km";
$moyennesData[$direction_label][$transportMode][] = $seconds;
}
else
{
$tmp[$direction_label]["timing"][$transportMode] = '';
$tmp[$direction_label]["distance"][$transportMode] = '';
}
}
// var_dump($timings);
// die();
}
$outputTimings[] = $tmp;
}
$moyennes = [];
foreach ($moyennesData as $directionLabel => $subData)
{
foreach ($subData as $tranportMode => $values)
{
$moyennes[$directionLabel][$tranportMode] = round(array_sum($values) / count($values)/60);
}
}
return $this->render('computing/show.html.twig', [
'moyennes' => $moyennes,
'timings' => $outputTimings,
'computing' => $computing,
]);
}
/**
* @Route("/{id}/edit", name="app_computing_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, Computing $computing, ComputingRepository $computingRepository): Response
{
$form = $this->createForm(ComputingType::class, $computing);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$computing->setLat(null);
//$computing->setLon(null);
$computingRepository->add($computing);
return $this->redirectToRoute('app_computing_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('computing/edit.html.twig', [
'computing' => $computing,
'form' => $form,
]);
}
/**
* @Route("/{id}/delete", name="app_computing_delete", methods={"POST"})
*/
public function delete(Request $request, Computing $computing, ComputingRepository $computingRepository, TimingRepository $timingRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$computing->getId(), $request->request->get('_token'))) {
$computingRepository->remove($computing , $timingRepository);
}
return $this->redirectToRoute('app_computing_index', [], Response::HTTP_SEE_OTHER);
}
/**
* @Route("/{id}/export/excell", name="app_computing_export_excell", methods={"GET"})
*/
public function excell_export( Computing $computing, ComputingRepository $computingRepository, TimingRepository $timingRepository)
{
$excell_tpl = $this->getParameter('kernel.project_dir')."/public/ekotools/templates/Ekotools_generated_template.xls";
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$spreadsheet = $reader->load($excell_tpl);
$sheet = $spreadsheet->getActiveSheet();
// $sheet->setCellValue('A1', 'Hello World !');
$addressesList = $computing->getAddressesGroup();
$addresses = $addressesList->getAddresses();
$transportModes = [];
$transportModes[] = DirectionsService::MODE_DRIVING_LABEL;
$transportModes[] = DirectionsService::MODE_TRANSIT_LABEL;
$transportModes[] = DirectionsService::MODE_BICYCLING_LABEL;
$transportModes[] = DirectionsService::MODE_WALKING_LABEL;
$directions = ['aller' => Timing::DIRECTION_ALLER];
//$directions = ['aller' => Timing::DIRECTION_ALLER, 'retour' =>Timing::DIRECTION_RETOUR];
$row = 3;
foreach ($addresses as $address)
{
$row++;
$col = 1;
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow( $col, $row, $address->toString());
$col = 2;
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $computing->getAddresse());
foreach ($transportModes as $transportMode)
{
$transportModeID = DirectionsService::ConvertTransportModeToID($transportMode);
foreach ($directions as $direction_label => $direction)
{
$timings = $timingRepository->findTimingsByComputingAddressAndTransportMode($computing, $address, $transportModeID, $direction);
if(isset($timings[0]))
{
$seconds = $timings[0]->getTime();
$tmp[$direction_label]["timing"][$transportMode] = DataFormatService::formatSecond($seconds);
$tmp[$direction_label]["distance"][$transportMode] = round($timings[0]->getDistance()/1000, 2)."km";
$moyennesData[$direction_label][$transportMode][] = $seconds;
}
else
{
$tmp[$direction_label]["timing"][$transportMode] = '';
$tmp[$direction_label]["distance"][$transportMode] = '';
}
$col++;
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $seconds);
$col++;
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $timings[0]->getDistance());
$col++;
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, $timings[0]->getSteps());
$col++;
if($transportMode == DirectionsService::MODE_DRIVING_LABEL)
{
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, round($timings[0]->getDistance()*254/1000,0));
}
elseif($transportMode == DirectionsService::MODE_TRANSIT_LABEL)
{
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, round($timings[0]->getDistance()*0.08/1000,0));
}
else
{
$spreadsheet->getActiveSheet()->setCellValueByColumnAndRow($col, $row, 0);
}
}
}
$outputTimings[] = $tmp;
}
$writer = new Xlsx($spreadsheet);
$writer->save('generated/result.xlsx');
// This should return the file located in /mySymfonyProject/web/public-resources/TextFile.txt
// to being viewed in the Browser
return new BinaryFileResponse($this->getParameter('kernel.project_dir')."/public/generated/result.xlsx");
}
}