<?php
namespace App\Controller;
use App\Service\MeteoFranceService;
use App\DTO\StationMeteoDTO;
use App\Form\StationMeteoType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Pluviometrie;
use App\Entity\StationsMeteo;
set_time_limit(36000);
class MeteoController extends AbstractController {
// private HttpClientInterface $client;
// private CacheInterface $cache;
// private string $apiKey;
// private string $tokenUrl;
// private string $apiUrl;
public function __construct(private MeteoFranceService $meteoService, StationMeteoType $stationMeteoType){//, HttpClientInterface $client, CacheInterface $cache, string $apiKey, string $meteoFranceTokenUrl, string $meteoFranceApiUrl) {
$this->stationMeteoType = $stationMeteoType;
}
#[Route(path: '/meteo/stations/tous', name: 'meteo_stations_tous')]
public function getAllStationsData(EntityManagerInterface $em, \App\Repository\PluvioDatabaseRepository $pluvioRepo,
Request $req): Response {
// Liste des départements (exemple de 5 départements, tu peux en ajouter plus)
$departements = ['974','976','984', '985','986','987','988'];
//'17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32',
//'33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57',
//'58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82',
//'83','84','85','86','87','88','89','90','91','92','93','94','95','971','972','973',
//, ,
//'11','12','13','14','15','16',
// '01','02']; '05','06','07','08','09','10'// Remplace par la liste complète des départements
//[
//'75','92', '69','91','13','31','44',
//'33'//,'35','51','06','67','38','73','63','76',
// '26','53','45','59','16','84','79','2A','37','64','34','85','49','74','29','56','95','14','25','10',
// '86','42','77','87','54','71','39','50','60','17','22','72','41','83','90','28','52','12','05','89',
// '18','01','04','19','40','48','47','88','57','03','30','27','46','08','58','65','15','81','36','2B',
// '66','62','82','43','61','02','24','55','11','32','07','70','09','23'
//'78'//'93'//,'93',, '21'//
// ];
$stationsData = [];
$commandeArray = []; // Initialisation pour éviter l'erreur Undefined variable
$columnDataArray = []; // Initialisation pour stocker les données des colonnes
// Boucle pour récupérer les données pour chaque département
// foreach ($departements as $departement) {
// try {
// $stations = $this->meteoService->getStationsByDepartment($departement);
//
// // Ajouter le numéro du département à chaque station
// foreach ($stations as &$station) {
// $station['departement'] = $departement;
// }
//
// $stationsData[$departement] = $stations;
// } catch (\Exception $e) {
// $stationsData[$departement] = ['error' => $e->getMessage()];
// }
//
// // Pause pour respecter la limite de 50 requêtes par minute
// usleep(1300000); // 1,2 secondes = 1 200 000 microsecondes
//
// }
//
// dump($stationsData);
//
// foreach ($stationsData as $listeStationsDdepartement) {
//$listeStationsDdepartement = $em->getRepository(StationsMeteo::class)->findAll();
$listeStationsDdepartement = $em->getRepository(StationsMeteo::class)
->createQueryBuilder('s')
->where('s.departement > :min')
->andWhere('s.departement < :max')
->setParameter('min', 39)
->setParameter('max', 41)
->getQuery()
->getResult();
// Pour chaque station, on réalise une commande
foreach ($listeStationsDdepartement as $station) {
dump($station);
// if ($station['typePoste'] < 2) {
$stationId = $station->getIdStation();
dump($stationId);
$AnneesEtudiees = [];
foreach (range(2020, 2024) as $annee) {
$AnneesEtudiees[$annee] = [
'dateDeb' => "{$annee}-01-01T00%3A00%3A00Z",
'dateFin' => "{$annee}-12-31T00%3A00%3A00Z",
];
}
foreach ($AnneesEtudiees as $annee => $AnneeEtudiee) {
//check si déjà commandé ?
$dejaCommandee = null;
$stationEntity = $em->getRepository(StationsMeteo::class)->findOneBy(['IdStation' => $stationId]);
if ($stationEntity) {
$dejaCommandee = $em->getRepository(Pluviometrie::class)->findOneBy([
'idStation' => $stationEntity,
'annee' => $annee
]);
}
if (!$dejaCommandee) {
$commande = $this->meteoService->getStationData($stationId, $AnneeEtudiee);
$commandeArray[$stationId][$annee] = $commande;
// Pause pour respecter la limite de 50 requêtes par minute
usleep(1300000); // 1,2 secondes = 1 200 000 microsecondes
}
}
//$nomDesStations[] = $station['nom'];
$stationDB = $em->getRepository(StationsMeteo::class)->findOneBy(['IdStation' => $stationId]);
if (!$stationDB) {
// Si la station n'existe pas, alors crée-la
//saisie dans la bdd
$stationDB = new \App\Entity\StationsMeteo();
$stationDB->setNomStation($station['nom']);
$stationDB->setTypeStation($station['typePoste']);
$stationDB->setDepartement($station['departement']);
$stationDB->setIdStation($station['id']);
dump($stationDB);
$em->persist($stationDB);
$em->flush();
}
// }
}
// }
dump($commandeArray);
$erreur500 = null;
$extractedData = null;
// Récupération des fichiers à partir des commandes
foreach ($commandeArray as $stationId => $anneesData) {
dump($anneesData);
$erreur = null;
foreach ($anneesData as $AnneeEtudiee => $commandeAnnee) {
$commandeId = $commandeAnnee['elaboreProduitAvecDemandeResponse']['return'];
dump($commandeId);
$csvString = $this->meteoService->getFichier($commandeId);
// Pause pour respecter la limite de 50 requêtes par minute
usleep(1300000); // 1,2 secondes = 1 200 000 microsecondes
if ($csvString == 'Erreur 500'){
$erreur500[$commandeId] = $stationId;
$erreur = 1;
} else {
// Diviser la chaîne en lignes
$lines = explode("\n", $csvString);
// Tableau pour stocker les données extraites
$extractedData = [];
foreach ($lines as $index => $line) {
// Ignorer la première ligne (en-tête)
if ($index === 0) {
continue;
}
// Diviser chaque ligne en colonnes par le séparateur ;
$columns = explode(";", $line);
// Vérifier qu'il y a suffisamment de colonnes
if (count($columns) > 2) {
// Extraire ce qui se situe entre le 3ème et 4ème point-virgule
$data = $columns[2]; // Récupère la valeur de l'élément à l'index 2 (entre 3ème et 4ème point-virgule)
// Remplacer les virgules par des points
$data = str_replace(",", ".", $data);
$extractedData[] = $data;
}
}
// Création de l'entité Pluviometrie
$entity = new \App\Entity\Pluviometrie();
$entity->setRainData($extractedData);
dump($stationId);
// Vérifie si tu récupères bien l'entité StationsMeteo avant de l'assigner
$station = $em->getRepository(StationsMeteo::class)->findOneBy(['IdStation' => $stationId]);
if ($station) {
$entity->setIdStation($station); // Assigner l'entité StationMeteo
} else {
// Gérer le cas où la station n'existe pas
throw new \Exception("Station not found");
}
// Lier l'année à Pluviometrie
$entity->setAnnee($AnneeEtudiee);
// Persister l'entité
$em->persist($entity);
}
}
if (!$erreur){
$em->flush();
}
}
// Flush une seule fois après avoir traité toutes les données
$query = $em->createQueryBuilder()
->select('s.id') // On récupère uniquement l'ID de la station météo
->from(\App\Entity\Pluviometrie::class, 'p')
->join('p.idStation', 's') // Jointure avec StationsMeteo
->getQuery();
$idStations = $query->getResult();
dump($idStations); //die();
// Extraction des ID des stations météorologiques
$idStation = [];
foreach ($idStations as $idStation) {
$idStationArray[] = $idStation['id'];
}
dump($idStationArray);
// Supprimer les doublons d'ID
$listeUniqueIdStation = array_unique($idStationArray);
dump($listeUniqueIdStation);
// Récupérer toutes les stations correspondantes
$stationDBAll = $em->getRepository(\App\Entity\StationsMeteo::class)
->findBy(['id' => $listeUniqueIdStation], ['departement' => 'ASC']);
dump($stationDBAll); //die();
return $this->render('meteoFrance.html.twig', ['stationDBAll' => $stationDBAll]);
}
#[Route(path: '/meteo/listeStation', name: 'listeStation')]
public function listeStation(EntityManagerInterface $em, \App\Repository\PluvioDatabaseRepository $pluvioRepo,
Request $req): Response {
$stationDBAll = $em->getRepository(StationsMeteo::class)->findAll();
return $this->render('meteoFrance.html.twig', ['stationDBAll' => $stationDBAll]);
}
#[Route(path: '/meteo/station/{stationId}', name: 'meteo_station_data')]
public function getStationData(string $stationId): JsonResponse {
try {
// Récupérer les données pour la station spécifiée et la période
$data = $this->meteoService->getStationData($stationId);
return new JsonResponse($data); // Retourner les données au format JSON
} catch (\Exception $e) {
return new JsonResponse(['error' => $e->getMessage()]);
}
}
#[Route(path: '/meteo/commande/{commandeId}', name: 'meteo_commande')]
public function getFichier(string $commandeId): Response {
// Récupérer les données pour la station spécifiée et la période
$data = $this->meteoService->getFichier($commandeId);
return new Response(
$data,
Response::HTTP_OK,
['Content-Type' => 'text/plain']
);
}
#[Route(path: '/meteo/stations/{departmentId}/precipitation', name: 'meteo_stations', methods: ['GET'])]
public function getStations(string $departmentId) {
// Récupérer les données pour le département spécifié
$data = $this->meteoService->getStationsByDepartment($departmentId);
dump($data);
// Retourner les données sous forme de réponse JSON
return new JsonResponse($data);
}
#[Route(path: '/meteo/commande/tous', name: 'commande_tous')]
public function getCommandeData(): JsonResponse {
// Liste des départements (exemple de 5 départements, tu peux en ajouter plus)
$departements = ['01', '02']; // Remplace par la liste complète des départements
$stationsData = [];
// Boucle pour récupérer les données pour chaque département
foreach ($departements as $departement) {
// try {
dump($departement);
$stationsData[$departement] = $this->meteoService->getStationsByDepartment($departement);
// } catch (\Exception $e) {
// $stationsData[$departement] = ['error' => $e->getMessage()];
// }
}
dump($stationsData);
// Pour chaque station, on réalise une commande
//$commandeArray = $this->meteoService->getStationData($stationId);
// Pour chaque commande, on obtient un fichier
//$fichier = $this->meteoService->getFichier($commandeId);
return $this->render('meteoFrance.html.twig');
}
// #[Route(path: '/meteo/testToken', name: 'testToken')]
// public function gettestToken(string $tokenUrl): Response {
//
// // Récupérer les données pour la station spécifiée et la période
// $tokenUrl = $this->meteoService->getrefreshToken();
// return new Response(
// $tokenUrl,
// Response::HTTP_OK,
// ['Content-Type' => 'text/plain']
// );
// }
#[Route(path: '/meteo/listeDesStations', name: 'listeDesStations')]
public function listeDesStations(EntityManagerInterface $em, \App\Repository\PluvioDatabaseRepository $pluvioRepo, Request $req): Response
{
// Récupération de toutes les données de pluviométrie
//$pluviometrieAll = $em->getRepository(\App\Entity\Pluviometrie::class)->findAll();
$query = $em->createQueryBuilder()
->select('s.id') // On récupère uniquement l'ID de la station météo
->from(\App\Entity\Pluviometrie::class, 'p')
->join('p.idStation', 's') // Jointure avec StationsMeteo
->getQuery();
$idStations = $query->getResult();
dump($idStations); //die();
// Extraction des ID des stations météorologiques
$idStation = [];
foreach ($idStations as $idStation) {
$idStationArray[] = $idStation['id'];
}
dump($idStationArray);
// Supprimer les doublons d'ID
$listeUniqueIdStation = array_unique($idStationArray);
dump($listeUniqueIdStation);
// Récupérer toutes les stations correspondantes
$stationDBAll = $em->getRepository(\App\Entity\StationsMeteo::class)
->findBy(['id' => $listeUniqueIdStation], ['departement' => 'ASC']);
dump($stationDBAll); //die();
return $this->render('meteoFrance.html.twig', ['stationDBAll' => $stationDBAll]);
}
/**
* @Route("/chart", name="chart")
*/
public function index(Request $request): Response
{
// Créer une instance du DTO pour passer au formulaire
$stationMeteoDTO = new StationMeteoDTO();
// Créer le formulaire avec l'objet DTO
$form = $this->createForm(StationMeteoType::class, $stationMeteoDTO);
// Gérer la soumission du formulaire
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// Récupérer les données du formulaire
$data = $form->getData();
dump($data);
// Tu as directement accès à l'objet StationMeteoDTO ici
$apikey = $data->getApikey(); // Accès via la méthode getter
$stationAPI = $data->getStationAPI(); // Accès via la méthode getter
// Appeler le service pour obtenir les données météo
// try {
// $result = $this->météoService->getStationDataHoraire($data['stationId'], $AnneeEtudiee, $data['apiKey']);
$stationsData = [];
$commandeArray = []; // Initialisation pour éviter l'erreur Undefined variable
$columnDataArray = []; // Initialisation pour stocker les données des colonnes
$AnneesEtudiees = [];
foreach (range(2018, 2024) as $annee) {
$AnneesEtudiees[$annee] = [
'dateDeb' => "{$annee}-01-01T00%3A00%3A00Z",
'dateFin' => "{$annee}-12-31T00%3A00%3A00Z",
];
}
foreach ($AnneesEtudiees as $annee => $AnneeEtudiee) {
$commande = $this->meteoService->getStationDataHoraire($stationAPI, $AnneeEtudiee, $apikey);
$commandeArray[$stationAPI][$annee] = $commande;
// Pause pour respecter la limite de 50 requêtes par minute
usleep(1300000); // 1,2 secondes = 1 200 000 microsecondes
}
dump($commandeArray);
$erreur500 = null;
$extractedData = [];
// Récupération des fichiers à partir des commandes
foreach ($commandeArray as $stationAPI => $anneesData) {
dump($anneesData);
$erreur = null;
foreach ($anneesData as $AnneeEtudiee => $commandeAnnee) {
$commandeId = $commandeAnnee['elaboreProduitAvecDemandeResponse']['return'];
// dump($commandeId);
$csvString = $this->meteoService->getFichier($commandeId, $apikey);
// dump($csvString);
// Pause pour respecter la limite de 50 requêtes par minute
usleep(1300000); // 1,2 secondes = 1 200 000 microsecondes
if ($csvString == 'Erreur 500'){
$erreur500[$commandeId] = $stationId;
$erreur = 1;
} else {
// Diviser la chaîne en lignes
$lines = explode("\n", $csvString);
// Tableau pour stocker les données extraites
$data = [];
foreach ($lines as $index => $line) {
// Ignorer la première ligne (en-tête)
if ($index === 0) {
continue;
}
// Diviser chaque ligne en colonnes par le séparateur ;
$columns = explode(";", $line);
// Vérifier qu'il y a suffisamment de colonnes
if (count($columns) > 2) {
// Extraire ce qui se situe entre le 3ème et 4ème point-virgule
$data['date'] = str_replace(",", ".", $columns[1]);
$data['temperature'] = str_replace(",", ".", $columns[10]);
$data['vitesse'] = str_replace(",", ".", $columns[48]);
$data['direction'] = str_replace(",", ".", $columns[50]);
$extractedData[] = $data;
$extractedDataParAn[$AnneeEtudiee][] = $data;
}
}
}
}
}
// dump($extractedDataParAn);
$directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
$classesVitesse = [
'<1' => [0, 1],
'1–5' => [1, 5],
'5–10' => [5, 10],
'10–15' => [10, 15],
'>15' => [15, INF],
];
$roseDesVents = [];
foreach ($directions as $dir) {
foreach ($classesVitesse as $classe => $_) {
$roseDesVents[$dir][$classe] = 0;
}
$roseDesVents[$dir]['Total'] = 0;
}
function getWindDirection16($deg) {
$dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
$index = (int) round($deg / 22.5) % 16;
return $dirs[$index];
}
function getVitesseClasse($vitesse, $classesVitesse) {
foreach ($classesVitesse as $label => [$min, $max]) {
if ($vitesse >= $min && $vitesse < $max) {
return $label;
}
}
return '>10'; // fallback
}
$totalObservations = 0;
foreach ($extractedData as $data) {
$direction = floatval($data['direction']);
$vitesse = floatval($data['vitesse']);
if ($vitesse < 0 || $direction < 0 || $direction > 360)
continue;
$dirName = getWindDirection16($direction);
$classeVitesse = getVitesseClasse($vitesse, $classesVitesse);
$roseDesVents[$dirName][$classeVitesse]++;
$roseDesVents[$dirName]['Total']++;
$totalObservations++;
}
// Convertir en % de fréquence
foreach ($roseDesVents as $dir => $classes) {
foreach ($classesVitesse as $classe => $_) {
$count = $roseDesVents[$dir][$classe];
$roseDesVents[$dir][$classe] = round(($count / $totalObservations) * 100, 2);
}
// Total (par direction, toutes vitesses confondues)
$countTotal = $roseDesVents[$dir]['Total'];
$roseDesVents[$dir]['Total'] = round(($countTotal / $totalObservations) * 100, 2);
}
$stationKey = $this->getKeyById($stationAPI);
$summerData = [];
$winterData = [];
foreach ($extractedData as $data) {
// Récupérer l'année, le mois et le jour de la date
$date = $data['date']; // Assurez-vous que la date est au format AAAAMMJJHH
$year = substr($date, 0, 4); // AAAA
$month = substr($date, 4, 2); // MM
$day = substr($date, 6, 2); // JJ
// Vérifier si la date correspond à l'été (juin, juillet, août)
if (in_array($month, ['06', '07', '08'])) {
$summerData[] = $data;
}
// Vérifier si la date correspond à l'hiver (décembre, janvier, février)
elseif (in_array($month, ['12', '01', '02'])) {
$winterData[] = $data;
}
}
// Traiter les données d'été et d'hiver de la même manière que pour les données globales
$summerRoseDesVents = $this->processWindData($summerData, $classesVitesse);
$winterRoseDesVents = $this->processWindData($winterData, $classesVitesse);
// dump($summerRoseDesVents);
// dump($roseDesVents);
// Passer les données au template
return $this->render('chart.html.twig', [
'roseDesVents' => $roseDesVents,
'summerRoseDesVents' => $summerRoseDesVents,
'winterRoseDesVents' => $winterRoseDesVents,
'directions' => $directions,
'stationKey' => $stationKey,
'form' => $form->createView(),
]);
// } catch (\Exception $e) {
// // Gérer les erreurs
// $this->addFlash('error', 'Erreur : ' . $e->getMessage());
// }
}
// Rendre la vue du formulaire
return $this->render('formulaireWindrose.html.twig', [
'form' => $form->createView(),
]);
}
// Méthode pour obtenir la clé en fonction de l'ID
public function getKeyById($id)
{
// Récupérer le tableau des stations et IDs à partir de StationMeteoType
$choices = $this->stationMeteoType->getStationAPIChoices();
// Rechercher la clé correspondant à l'ID
$key = array_search($id, $choices);
// Si l'ID est trouvé, retourne la clé, sinon retourne null
return $key !== false ? $key : null;
}
private function processWindData(array $data, array $classesVitesse)
{
$roseDesVents = [];
foreach ($data as $dataPoint) {
$direction = floatval($dataPoint['direction']);
$vitesse = floatval($dataPoint['vitesse']);
if ($vitesse < 0 || $direction < 0 || $direction > 360) {
continue;
}
$dirName = getWindDirection16($direction);
$classeVitesse = getVitesseClasse($vitesse, $classesVitesse);
if (!isset($roseDesVents[$dirName])) {
$roseDesVents[$dirName] = [];
}
if (!isset($roseDesVents[$dirName][$classeVitesse])) {
$roseDesVents[$dirName][$classeVitesse] = 0;
}
$roseDesVents[$dirName][$classeVitesse]++;
}
// Convertir en % de fréquence
$totalObservations = array_sum(array_map(function ($direction) {
return array_sum($direction);
}, $roseDesVents));
//dump($roseDesVents);
// S'assurer que chaque direction contient toutes les classes avec une valeur par défaut
foreach ($roseDesVents as $dir => &$classes) {
foreach ($classesVitesse as $classe => $_) {
if (!isset($classes[$classe])) {
$classes[$classe] = 0;
}
}
}
// Important : libérer la référence
unset($classes);
// Ensuite, tu peux faire le calcul des pourcentages
foreach ($roseDesVents as $dir => $classes) {
foreach ($classesVitesse as $classe => $_) {
$count = $roseDesVents[$dir][$classe];
$roseDesVents[$dir][$classe] = round(($count / $totalObservations) * 100, 2);
}
// Pareil pour Total (si tu veux l’inclure dans le tableau final)
$roseDesVents[$dir]['Total'] = round((array_sum($roseDesVents[$dir]) / 100), 2);
}
return $roseDesVents;
}
}