From 409bff6d4c3bb6b477f1eadb7929aa212458eef7 Mon Sep 17 00:00:00 2001 From: Tykayn Date: Thu, 5 Jun 2025 16:20:20 +0200 Subject: [PATCH] up without batch --- src/Controller/AdminController.php | 215 ++++++++------------------- src/Entity/Place.php | 2 +- src/Service/Motocultrice.php | 43 +++--- templates/public/dashboard.html.twig | 27 +--- 4 files changed, 86 insertions(+), 201 deletions(-) diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php index 41fff9e..842bff2 100644 --- a/src/Controller/AdminController.php +++ b/src/Controller/AdminController.php @@ -125,165 +125,82 @@ final class AdminController extends AbstractController * récupérer les commerces de la zone, créer les nouveaux lieux, et mettre à jour les existants */ #[Route('/admin/labourer/{zip_code}', name: 'app_admin_labourer')] - public function labourer_zone(string $zip_code): Response + public function labourer(string $zip_code, bool $updateExisting = false): Response { - $results = []; - $results = $this->motocultrice->labourer($zip_code); - - - - // Récupérer ou créer les stats pour cette zone - $stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $zip_code]); - - - if (!$stats) { - $stats = new Stats(); - $stats->setZone($zip_code); - - // Récupérer les commerces existants dans la base de données pour cette zone - - - - } - $commerces = $stats->getPlaces(); -// for commerce, set stats - foreach ($commerces as $commerce) { - $commerce->setStats($stats); - $this->entityManager->persist($commerce); - $stats->addPlace($commerce); - } - - // rebuild et persist - $stats->computeCompletionPercent(); - $this->entityManager->persist($stats); - $this->entityManager->flush(); - - $stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $zip_code]); - // Si le nom de la zone n'est pas défini, le récupérer via OSM - if (!$stats->getName()) { - $city_name = $this->motocultrice->get_city_osm_from_zip_code($zip_code); - if ($city_name) { - $stats->setName($city_name); + try { + // Récupérer ou créer les stats pour cette zone + $stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $zip_code]); + if (!$stats) { + $stats = new Stats(); + $stats->setZone($zip_code) + ->setPlacesCount(0) + ->setAvecHoraires(0) + ->setAvecAdresse(0) + ->setAvecSite(0) + ->setAvecAccessibilite(0) + ->setAvecNote(0) + ->setCompletionPercent(0); $this->entityManager->persist($stats); $this->entityManager->flush(); } - } - // Initialiser les compteurs - $counters = [ - 'avec_horaires' => 0, - 'avec_adresse' => 0, - 'avec_site' => 0, - 'avec_accessibilite' => 0, - 'avec_note' => 0 - ]; - - // Compter les différents critères pour chaque commerce - foreach ($stats->getPlaces() as $commerce) { - if ($commerce->hasOpeningHours()) { - $counters['avec_horaires']++; - } - if ($commerce->hasAddress()) { - $counters['avec_adresse']++; - } - if ($commerce->hasWebsite()) { - $counters['avec_site']++; - } - if ($commerce->hasWheelchair()) { - $counters['avec_accessibilite']++; - } - if ($commerce->hasNote()) { - $counters['avec_note']++; - } - $commerce->setStats($stats); - } - - // Mettre à jour les statistiques - $stats->setPlacesCount(count($commerces)); - $stats->setAvecHoraires($counters['avec_horaires']); - $stats->setAvecAdresse($counters['avec_adresse']); - $stats->setAvecSite($counters['avec_site']); - $stats->setAvecAccessibilite($counters['avec_accessibilite']); - $stats->setAvecNote($counters['avec_note']); - $stats->computeCompletionPercent(); - - $this->entityManager->persist($stats); - $this->entityManager->flush(); - - $osm_object_ids = []; - - if ($commerces) { - // Extraire les osm_object_ids des commerces existants - foreach ($commerces as $commerce) { - $osm_object_ids[] = $commerce->getOsmKind() . '_' . $commerce->getOsmId(); - } - } - // pour chaque résultat, vérifier que l'on a pas déjà un commerce avec le même osm_object_id - - $new_places_list = array_filter($results, function($commerce) use ($osm_object_ids) { - return !in_array($commerce['type'] . '_' . $commerce['id'], $osm_object_ids); - }); - $existing_places_list = array_filter($results, function($commerce) use ($osm_object_ids) { - return in_array($commerce['type'] . '_' . $commerce['id'], $osm_object_ids); - }); - - $new_places_counter = 0; - - // on crée un commerce pour chaque résultat qui reste - foreach ($new_places_list as $np) { - - if( !in_array($np['id'] . '_' . $np['type'] , $osm_object_ids )) { - $new_place = new Place(); - - $main_tag = $this->motocultrice->find_main_tag($np['tags']); - - $fullMainTag = $main_tag && isset($np['tags'][$main_tag]) ? $main_tag.'='.$np['tags'][$main_tag] : ""; - $new_place - ->setUuidForUrl($this->motocultrice->uuid_create()) - ->setModifiedDate(new \DateTime()) - ->setStats($stats) - ->setDead(false) - ->setOptedOut(false) - ->setZipCode($zip_code) - ->setOsmId($np['id']) - ->setMainTag($fullMainTag) - ->setOsmKind($np['type']) - ->setAskedHumainsSupport(false) - ->setLastContactAttemptDate(null) - ->update_place_from_overpass_data($np); - $this->entityManager->persist($new_place); - $new_place->setStats($stats); - - $stats->addPlace($new_place); - $new_places_counter++; - } - } - - // Mise à jour des commerces existants avec les données Overpass - foreach ($commerces as $existing_place) { - foreach ($results as $result) { - if ($existing_place->getOsmId() == $result['id'] && $existing_place->getOsmKind() == $result['type']) { - $existing_place->update_place_from_overpass_data($result); - $existing_place->setStats($stats); + // Récupérer toutes les données + $places = $this->motocultrice->labourer($zip_code); + $processedCount = 0; + $updatedCount = 0; + + foreach ($places as $placeData) { + // Vérifier si le lieu existe déjà + $existingPlace = $this->entityManager->getRepository(Place::class) + ->findOneBy(['osmId' => $placeData['id']]); + + if (!$existingPlace) { + $place = new Place(); + $place->setOsmId($placeData['id']) + ->setOsmKind($placeData['type']) + ->setZipCode($zip_code) + ->setUuidForUrl($this->motocultrice->uuid_create()) + ->setModifiedDate(new \DateTime()) + ->setStats($stats) + ->setDead(false) + ->setOptedOut(false) + ->setAskedHumainsSupport(false) + ->setLastContactAttemptDate(null) + ->setNote('') + ->setPlaceCount(0); - $this->entityManager->persist($existing_place); - break; + // Mettre à jour les données depuis Overpass + $place->update_place_from_overpass_data($placeData); + + $this->entityManager->persist($place); + $stats->addPlace($place); + $processedCount++; + } elseif ($updateExisting) { + // Mettre à jour les données depuis Overpass uniquement si updateExisting est true + $existingPlace->update_place_from_overpass_data($placeData); + $this->entityManager->persist($existingPlace); + $updatedCount++; } } + + // Flush final + $this->entityManager->flush(); + + // Mettre à jour les statistiques finales + $stats->computeCompletionPercent(); + $this->entityManager->persist($stats); + $this->entityManager->flush(); + + $message = 'Labourage terminé avec succès. ' . $processedCount . ' nouveaux lieux traités.'; + if ($updateExisting) { + $message .= ' ' . $updatedCount . ' lieux existants mis à jour.'; + } + $this->addFlash('success', $message); + } catch (\Exception $e) { + $this->addFlash('error', 'Erreur lors du labourage : ' . $e->getMessage()); } - $this->entityManager->persist($stats); - $this->entityManager->flush(); - - - $stats = $this->entityManager->getRepository(Stats::class)->findOneBy(['zone' => $zip_code]); - return $this->render('admin/labourage_results.html.twig', [ - 'results' => $results, - 'commerces' => $stats->getPlaces(), - 'zone' => $zip_code, - 'stats' => $stats, - 'new_places_counter' => $new_places_counter, - ]); + return $this->redirectToRoute('app_public_dashboard'); } #[Route('/admin/delete/{id}', name: 'app_admin_delete')] diff --git a/src/Entity/Place.php b/src/Entity/Place.php index a624286..c1778cc 100644 --- a/src/Entity/Place.php +++ b/src/Entity/Place.php @@ -52,7 +52,7 @@ class Place #[ORM\OneToMany(targetEntity: History::class, mappedBy: 'place_id', orphanRemoval: true)] private Collection $histories; - #[ORM\ManyToOne(inversedBy: 'places')] + #[ORM\ManyToOne(inversedBy: 'places', cascade: ['persist'])] private ?Stats $stats = null; #[ORM\Column(type: Types::BIGINT)] diff --git a/src/Service/Motocultrice.php b/src/Service/Motocultrice.php index 9ec2087..c83357c 100644 --- a/src/Service/Motocultrice.php +++ b/src/Service/Motocultrice.php @@ -12,7 +12,7 @@ class Motocultrice public $overpass_base_places = ' ( - nw["amenity"~"^(cafe|bar|restaurant|library|cinema|fast_food|post_office|marketplace|community_centre|theatre|bank|townhall|animal_boarding|animal_breeding|animal_shelter|animal_training|archive|arts_centre|bank|bar|bicycle_rental|biergarten|boat_rental|boat_storage|bureau_de_change|cafe|canteen|car_rental|car_wash|casino|childcare|clinic|college|conference_centre|courthouse|coworking_space|crematorium|dancing_school|dentist|dive_centre|doctors|dojo|driver_training|driving_school|events_venue|financial_advice|fire_station|flight_school|food_court|fuel|funeral_hall|hookah_lounge|hospital|ice_cream|internet_cafe|karaoke_box|kindergarten|language_school|love_hotel|medical_supply|monastery|money_transfer|motorcycle_rental|music_school|music_venue|nightclub|nursing_home|pharmacy|place_of_mourning|place_of_worship|police|post_depot|prep_school|prison|pub|public_bath|ranger_station|research_institute|sailing_school|school|ski_rental|ski_school|social_centre|social_facility|stripclub|student_accommodation|studio|surf_school|swingerclub|theatre|toy_library|university|vehicle_inspection|veterinary|waste_transfer_station|workshop|art_school|atm|bar||bicycle_parking|bicycle_repair_station|boat_school|bus_station|clock|clubhouse|coffee|construction_equipment_rental|cooking_school|deposit_sale|dog_toilet|drive_school|estate_agent|event|fixme|florist|groundskeeping|group_home|health_facility|healthcare|hearing_aid|hearing_aids|herbalist|laboratory|office|parcel_locker|personal_service|photo_booth|printer|professional_school|public_building|public_service|recycling|scuba_diving_school|septic_tank|software_engineering|spa|swingerclub for swinger clubs|taxi|teahouse|toilets|training|underprivileged|vehicule_inspection|vending_machine|warehouse)$"](area.searchArea); + nw["amenity"~"^(cafe|bar|restaurant|library|cinema|fast_food|post_office|marketplace|community_centre|theatre|bank|townhall|animal_boarding|animal_breeding|animal_shelter|animal_training|archive|arts_centre|bank|bar|bicycle_rental|biergarten|boat_rental|boat_storage|bureau_de_change|cafe|canteen|car_rental|car_wash|casino|childcare|clinic|college|conference_centre|courthouse|coworking_space|crematorium|dancing_school|dentist|dive_centre|doctors)$"](area.searchArea); nw["shop"](area.searchArea); nw["healthcare"](area.searchArea); nw["office"](area.searchArea); @@ -155,42 +155,33 @@ out center tags;'; public function labourer(string $zone): array { try { + $query = $this->get_query_places($zone); $response = $this->client->request('POST', $this->overpassApiUrl, [ - 'body' => ['data' => $this->get_query_places($zone)] + 'body' => ['data' => $query] ]); $data = json_decode($response->getContent(), true); $places = []; if (isset($data['elements'])) { - $batchSize = 100; // Traiter par lots de 100 éléments - $totalElements = count($data['elements']); - - for ($i = 0; $i < $totalElements; $i += $batchSize) { - $batch = array_slice($data['elements'], $i, $batchSize); - - foreach ($batch as $element) { - if (isset($element['tags'])) { - $email = ""; - - $places[] = [ - 'id' => $element['id'], - 'type' => $element['type'], - 'name' => $element['tags']['name'] ?? '', - 'email' => $email, - 'lat' => $element['lat'] ?? null, - 'lon' => $element['lon'] ?? null, - 'tags' => $element['tags'] - ]; - } + foreach ($data['elements'] as $element) { + if (isset($element['tags'])) { + $places[] = [ + 'id' => $element['id'], + 'type' => $element['type'], + 'name' => $element['tags']['name'] ?? '', + 'lat' => $element['lat'] ?? null, + 'lon' => $element['lon'] ?? null, + 'tags' => $element['tags'] + ]; } - - // Libérer la mémoire après chaque lot - unset($batch); - gc_collect_cycles(); } } + // Libérer la mémoire + unset($data); + gc_collect_cycles(); + return $places; } catch (\Exception $e) { throw new \Exception("Erreur lors de la requête Overpass : " . $e->getMessage()); diff --git a/templates/public/dashboard.html.twig b/templates/public/dashboard.html.twig index 6496270..6fc0003 100644 --- a/templates/public/dashboard.html.twig +++ b/templates/public/dashboard.html.twig @@ -215,31 +215,8 @@ out skel qt;`; {% endfor %} - - - {% if totalPages > 1 %} - - {% endif %} + +

{{ places_count }} Lieux