getParameter('kernel.project_dir') . '/var/fraicheur_osm.json'; if (!file_exists($jsonPath)) { $this->calculateFraicheur(); } return $this->render('admin/fraicheur_histogramme.html.twig'); } #[Route('/admin/fraicheur/calculate', name: 'admin_fraicheur_calculate')] public function calculateFraicheur(): Response { $filesystem = new Filesystem(); $jsonPath = $this->getParameter('kernel.project_dir') . '/var/fraicheur_osm.json'; $now = new \DateTime(); $placeRepo = $this->entityManager->getRepository(Place::class); $query = $placeRepo->createQueryBuilder('p')->getQuery(); $places = $query->toIterable(); $histogram = []; $total = 0; foreach ($places as $place) { $date = $place->getOsmDataDate(); if ($date) { $key = $date->format('Y-m'); if (!isset($histogram[$key])) { $histogram[$key] = 0; } $histogram[$key]++; $total++; } $this->entityManager->detach($place); } ksort($histogram); $data = [ 'generated_at' => $now->format('c'), 'total' => $total, 'histogram' => $histogram ]; $filesystem->dumpFile($jsonPath, json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); // --- Distribution villes selon lieux/habitants --- $distJsonPath = $this->getParameter('kernel.project_dir') . '/var/distribution_villes_lieux_par_habitant.json'; $statsRepo = $this->entityManager->getRepository(Stats::class); $queryStats = $statsRepo->createQueryBuilder('s')->getQuery(); $allStats = $queryStats->toIterable(); $histogram_lieux_par_habitant = []; $histogram_habitants_par_lieu = []; $villesByBinLph = []; $villesByBinHpl = []; $totalVilles = 0; foreach ($allStats as $stat) { $places = $stat->getPlacesCount(); $population = $stat->getPopulation(); $name = $stat->getName(); if ($places && $population && $population > 0 && $name) { // lieux par habitant (pas de 0.01) $ratio_lph = $places / $population; $bin_lph = number_format(floor($ratio_lph / 0.01) * 0.01, 2, '.', ''); if (!isset($histogram_lieux_par_habitant[$bin_lph])) $histogram_lieux_par_habitant[$bin_lph] = 0; $histogram_lieux_par_habitant[$bin_lph]++; if (!isset($villesByBinLph[$bin_lph])) $villesByBinLph[$bin_lph] = []; $villesByBinLph[$bin_lph][] = $name; // habitants par lieu (pas de 10) $ratio_hpl = $population / $places; $bin_hpl = (string)(ceil($ratio_hpl / 10) * 10); if (!isset($histogram_habitants_par_lieu[$bin_hpl])) $histogram_habitants_par_lieu[$bin_hpl] = 0; $histogram_habitants_par_lieu[$bin_hpl]++; if (!isset($villesByBinHpl[$bin_hpl])) $villesByBinHpl[$bin_hpl] = []; $villesByBinHpl[$bin_hpl][] = $name; $totalVilles++; } $this->entityManager->detach($stat); } ksort($histogram_lieux_par_habitant); ksort($histogram_habitants_par_lieu); ksort($villesByBinLph); ksort($villesByBinHpl); $distData = [ 'generated_at' => $now->format('c'), 'total_villes' => $totalVilles, 'histogram_001' => $histogram_lieux_par_habitant, 'histogram_10' => $histogram_habitants_par_lieu, 'villes_by_bin_001' => $villesByBinLph, 'villes_by_bin_10' => $villesByBinHpl ]; $filesystem->dumpFile($distJsonPath, json_encode($distData, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); // --- Statistiques budgétaires --- // Remplir les budgets manquants avant le calcul $this->budgetService->fillMissingBudgetsForAllStats($this->entityManager); $this->calculateBudgetStats(); return $this->redirectToRoute('admin_fraicheur_histogramme'); } /** * Calcule les statistiques liées au budget des villes */ private function calculateBudgetStats(): void { $filesystem = new Filesystem(); $budgetJsonPath = $this->getParameter('kernel.project_dir') . '/var/budget_stats.json'; $now = new \DateTime(); $statsRepo = $this->entityManager->getRepository(Stats::class); $queryStats = $statsRepo->createQueryBuilder('s')->getQuery(); $allStats = $queryStats->toIterable(); $budgetParHabitant = []; $villesAvecBudget = []; $totalBudget = 0; $totalPopulation = 0; $budgetParLieu = []; $villesByBinBudgetParLieu = []; $histogramBudgetParLieu = []; // Collecter les données de budget par habitant et par lieu foreach ($allStats as $stat) { $budgetAnnuel = $stat->getBudgetAnnuel(); $population = $stat->getPopulation(); $placesCount = $stat->getPlacesCount(); $name = $stat->getName(); if ($budgetAnnuel && $population && $population > 0 && $name) { $budgetParHabitantValue = (float)$budgetAnnuel / $population; $budgetParHabitant[] = [ 'ville' => $name, 'code_insee' => $stat->getZone(), 'budget_annuel' => (float)$budgetAnnuel, 'population' => $population, 'budget_par_habitant' => $budgetParHabitantValue ]; $villesAvecBudget[] = $name; $totalBudget += (float)$budgetAnnuel; $totalPopulation += $population; } // Ajout budget par lieu if ($budgetAnnuel && $placesCount && $placesCount > 0 && $name) { $budgetParLieuValue = (float)$budgetAnnuel / $placesCount; $budgetParLieu[] = [ 'ville' => $name, 'code_insee' => $stat->getZone(), 'budget_annuel' => (float)$budgetAnnuel, 'places_count' => $placesCount, 'budget_par_lieu' => $budgetParLieuValue ]; $binBudgetParLieu = (string)(ceil($budgetParLieuValue / 5000) * 5000); if (!isset($histogramBudgetParLieu[$binBudgetParLieu])) $histogramBudgetParLieu[$binBudgetParLieu] = 0; $histogramBudgetParLieu[$binBudgetParLieu]++; if (!isset($villesByBinBudgetParLieu[$binBudgetParLieu])) $villesByBinBudgetParLieu[$binBudgetParLieu] = []; $villesByBinBudgetParLieu[$binBudgetParLieu][] = $name; } $this->entityManager->detach($stat); } // Calculer la moyenne du budget par habitant $moyenneBudgetParHabitant = $totalPopulation > 0 ? $totalBudget / $totalPopulation : 0; // Calculer l'écart à la moyenne pour chaque ville $ecartsMoyenne = []; foreach ($budgetParHabitant as $ville) { $ecart = $this->budgetService->getEcartMoyenneBudgetParHabitant( $ville['budget_par_habitant'], $moyenneBudgetParHabitant ); $ecartsMoyenne[] = [ 'ville' => $ville['ville'], 'code_insee' => $ville['code_insee'], 'budget_par_habitant' => $ville['budget_par_habitant'], 'ecart_moyenne_pourcent' => $ecart ]; } // Créer des histogrammes $histogramBudgetParHabitant = []; $histogramEcartMoyenne = []; $villesByBinBudget = []; $villesByBinEcart = []; foreach ($budgetParHabitant as $ville) { // Histogramme budget par habitant (pas de 100€) $binBudget = (string)(ceil($ville['budget_par_habitant'] / 100) * 100); if (!isset($histogramBudgetParHabitant[$binBudget])) { $histogramBudgetParHabitant[$binBudget] = 0; } $histogramBudgetParHabitant[$binBudget]++; if (!isset($villesByBinBudget[$binBudget])) { $villesByBinBudget[$binBudget] = []; } $villesByBinBudget[$binBudget][] = $ville['ville']; } foreach ($ecartsMoyenne as $ville) { // Histogramme écart à la moyenne (pas de 10%) $binEcart = (string)(ceil($ville['ecart_moyenne_pourcent'] / 10) * 10); if (!isset($histogramEcartMoyenne[$binEcart])) { $histogramEcartMoyenne[$binEcart] = 0; } $histogramEcartMoyenne[$binEcart]++; if (!isset($villesByBinEcart[$binEcart])) { $villesByBinEcart[$binEcart] = []; } $villesByBinEcart[$binEcart][] = $ville['ville']; } ksort($histogramBudgetParHabitant); ksort($histogramEcartMoyenne); ksort($villesByBinBudget); ksort($villesByBinEcart); ksort($histogramBudgetParLieu); ksort($villesByBinBudgetParLieu); $budgetData = [ 'generated_at' => $now->format('c'), 'total_villes_avec_budget' => count($villesAvecBudget), 'moyenne_budget_par_habitant' => $moyenneBudgetParHabitant, 'total_budget' => $totalBudget, 'total_population' => $totalPopulation, 'villes_avec_budget' => $villesAvecBudget, 'budget_par_habitant' => $budgetParHabitant, 'budget_par_lieu' => $budgetParLieu, 'ecarts_moyenne' => $ecartsMoyenne, 'histogram_budget_par_habitant' => $histogramBudgetParHabitant, 'histogram_ecart_moyenne' => $histogramEcartMoyenne, 'villes_by_bin_budget' => $villesByBinBudget, 'villes_by_bin_ecart' => $villesByBinEcart, 'histogram_budget_par_lieu' => $histogramBudgetParLieu, 'villes_by_bin_budget_par_lieu' => $villesByBinBudgetParLieu ]; $filesystem->dumpFile($budgetJsonPath, json_encode($budgetData, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); } #[Route('/admin/fraicheur/download', name: 'admin_fraicheur_download')] public function downloadFraicheur(): JsonResponse { $jsonPath = $this->getParameter('kernel.project_dir') . '/var/fraicheur_osm.json'; if (!file_exists($jsonPath)) { return new JsonResponse(['error' => 'Fichier non généré'], 404); } $content = file_get_contents($jsonPath); $data = json_decode($content, true); return new JsonResponse($data); } #[Route('/admin/distribution_villes_lieux_par_habitant_download', name: 'admin_distribution_villes_lieux_par_habitant_download')] public function downloadDistributionVillesLieuxParHabitant(): JsonResponse { $jsonPath = $this->getParameter('kernel.project_dir') . '/var/distribution_villes_lieux_par_habitant.json'; if (!file_exists($jsonPath)) { $this->calculateFraicheur(); } $content = file_get_contents($jsonPath); $data = json_decode($content, true); return new JsonResponse($data); } #[Route('/admin/distribution_villes_lieux_par_habitant_villes', name: 'admin_distribution_villes_lieux_par_habitant_villes')] public function downloadDistributionVillesLieuxParHabitantVilles(): JsonResponse { $jsonPath = $this->getParameter('kernel.project_dir') . '/var/distribution_villes_lieux_par_habitant.json'; if (!file_exists($jsonPath)) { $this->calculateFraicheur(); } $content = file_get_contents($jsonPath); $data = json_decode($content, true); // On renvoie les deux listes de villes par bin return new JsonResponse([ 'villes_by_bin_001' => $data['villes_by_bin_001'] ?? [], 'villes_by_bin_10' => $data['villes_by_bin_10'] ?? [] ]); } #[Route('/admin/budget/download', name: 'admin_budget_download')] public function downloadBudget(): JsonResponse { $jsonPath = $this->getParameter('kernel.project_dir') . '/var/budget_stats.json'; if (!file_exists($jsonPath)) { $this->calculateFraicheur(); } $content = file_get_contents($jsonPath); $data = json_decode($content, true); return new JsonResponse($data); } #[Route('/admin/budget/villes', name: 'admin_budget_villes')] public function downloadBudgetVilles(): JsonResponse { $jsonPath = $this->getParameter('kernel.project_dir') . '/var/budget_stats.json'; if (!file_exists($jsonPath)) { $this->calculateFraicheur(); } $content = file_get_contents($jsonPath); $data = json_decode($content, true); return new JsonResponse([ 'villes_by_bin_budget' => $data['villes_by_bin_budget'] ?? [], 'villes_by_bin_ecart' => $data['villes_by_bin_ecart'] ?? [] ]); } }