mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-06-20 01:44:42 +02:00
up without batch
This commit is contained in:
parent
4c1a7729a1
commit
409bff6d4c
4 changed files with 86 additions and 201 deletions
|
@ -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);
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
// 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);
|
||||
$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
|
||||
];
|
||||
// Récupérer toutes les données
|
||||
$places = $this->motocultrice->labourer($zip_code);
|
||||
$processedCount = 0;
|
||||
$updatedCount = 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);
|
||||
}
|
||||
foreach ($places as $placeData) {
|
||||
// Vérifier si le lieu existe déjà
|
||||
$existingPlace = $this->entityManager->getRepository(Place::class)
|
||||
->findOneBy(['osmId' => $placeData['id']]);
|
||||
|
||||
// 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
|
||||
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)
|
||||
->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);
|
||||
->setNote('')
|
||||
->setPlaceCount(0);
|
||||
|
||||
$stats->addPlace($new_place);
|
||||
$new_places_counter++;
|
||||
// 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++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
$this->entityManager->persist($existing_place);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
|
||||
$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')]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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,41 +155,32 @@ 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) {
|
||||
foreach ($data['elements'] 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']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Libérer la mémoire après chaque lot
|
||||
unset($batch);
|
||||
// Libérer la mémoire
|
||||
unset($data);
|
||||
gc_collect_cycles();
|
||||
}
|
||||
}
|
||||
|
||||
return $places;
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
@ -217,29 +217,6 @@ out skel qt;`;
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
{% if totalPages > 1 %}
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if currentPage > 1 %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path('app_public_dashboard', {'page': currentPage - 1}) }}">Précédent</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% for i in 1..totalPages %}
|
||||
<li class="page-item {% if i == currentPage %}active{% endif %}">
|
||||
<a class="page-link" href="{{ path('app_public_dashboard', {'page': i}) }}">{{ i }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% if currentPage < totalPages %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ path('app_public_dashboard', {'page': currentPage + 1}) }}">Suivant</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<h2>{{ places_count }} Lieux</h2>
|
||||
<h2><button class="btn btn-primary" id="labourer">Labourer les mises à jour</button></h2>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue