#!/usr/bin/env python3 """ Démonstration des fonctions utilitaires AASQA avancées =================================================== Ce script illustre l'utilisation des nouvelles fonctions utilitaires avancées pour analyser et rechercher dans les données AASQA. Fonctionnalités: - Recherche par nom d'organisme ou région - Statistiques détaillées sur la couverture - Validation de l'intégrité des données - Analyses comparatives """ import sys import os # Ajouter le répertoire parent au PYTHONPATH pour importer le package local sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from atmo_data_wrapper import ( search_aasqa_by_name, get_departments_count, validate_department_coverage, get_aasqa_statistics, get_aasqa_info ) def demo_search_functionality(): """Démonstration de la recherche par nom""" print("🔍 RECHERCHE PAR NOM D'ORGANISME OU RÉGION") print("=" * 55) search_terms = ['Atmo', 'Air', 'France', 'Sud', 'Grand'] for term in search_terms: results = search_aasqa_by_name(term) print(f"🔎 Recherche '{term}' → {len(results)} résultat(s)") for result in results[:3]: # Limiter à 3 résultats pour la démo print(f" • {result['organisme']} ({result['region']})") if len(results) > 3: print(f" ... et {len(results) - 3} autre(s)") print() def demo_department_statistics(): """Démonstration des statistiques départementales""" print("📊 STATISTIQUES DÉPARTEMENTALES") print("=" * 55) dept_counts = get_departments_count() # Tri par nombre de départements (décroissant) sorted_counts = sorted(dept_counts.items(), key=lambda x: x[1], reverse=True) print("Classement par nombre de départements couverts:") print() for i, (aasqa_code, count) in enumerate(sorted_counts, 1): aasqa_info = get_aasqa_info(aasqa_code) organisme = aasqa_info['organisme'] region = aasqa_info['region'] if i <= 5: # Top 5 print(f"{i:2d}. {organisme:<30} : {count:2d} département(s) ({region})") elif i == 6: print(" ...") elif i >= len(sorted_counts) - 2: # Bottom 3 print(f"{i:2d}. {organisme:<30} : {count:2d} département(s) ({region})") print() def demo_validation_report(): """Démonstration du rapport de validation""" print("✅ RAPPORT DE VALIDATION") print("=" * 55) validation = validate_department_coverage() print("Intégrité des données AASQA:") print() print(f"📊 Total d'entrées départements: {validation['total_departments']}") print(f"📊 Départements uniques: {validation['unique_departments']}") print(f"📊 Couverture complète: {'✅ Oui' if validation['coverage_complete'] else '❌ Non'}") print(f"📊 Doublons détectés: {'❌ Oui' if validation['has_duplicates'] else '✅ Non'}") if validation['duplicates']: print(f"⚠️ Départements en doublon: {', '.join(validation['duplicates'])}") print() def demo_comprehensive_statistics(): """Démonstration des statistiques complètes""" print("📈 STATISTIQUES COMPLÈTES") print("=" * 55) stats = get_aasqa_statistics() print("Vue d'ensemble:") print(f" • Nombre total d'AASQA: {stats['total_aasqa']}") print(f" • Départements couverts: {stats['total_departments_covered']}") print(f" • Départements uniques: {stats['unique_departments']}") print(f" • Couverture moyenne: {stats['average_coverage']:.1f} départements/AASQA") print() print("Couverture maximale:") max_info = stats['max_coverage'] print(f" • {max_info['count']} départements") print(f" • Organisme(s): {', '.join(max_info['aasqa_names'])}") print() print("Couverture minimale:") min_info = stats['min_coverage'] print(f" • {min_info['count']} département(s)") print(f" • Organisme(s): {', '.join(min_info['aasqa_names'])}") print() print(f"Anomalies: {'❌ Détectées' if stats['has_anomalies'] else '✅ Aucune'}") print() def demo_practical_analysis(): """Démonstration d'analyses pratiques""" print("🎯 ANALYSES PRATIQUES") print("=" * 55) # Analyse 1: Organismes DOM-TOM print("1️⃣ Analyse DOM-TOM:") dom_tom_codes = ['971', '972', '973', '974', '976'] from atmo_data_wrapper import get_aasqa_by_department for code in dom_tom_codes: aasqa_code = get_aasqa_by_department(code) if aasqa_code: aasqa_info = get_aasqa_info(aasqa_code) print(f" • {code}: {aasqa_info['region']} → {aasqa_info['organisme']}") print() # Analyse 2: Régions métropolitaines les plus étendues print("2️⃣ Grandes régions métropolitaines:") dept_counts = get_departments_count() metro_counts = {} for aasqa_code, count in dept_counts.items(): aasqa_info = get_aasqa_info(aasqa_code) # Exclure DOM-TOM (codes postaux 97x) if not any(dept.startswith('97') for dept in aasqa_info['departements']): metro_counts[aasqa_code] = count top_metro = sorted(metro_counts.items(), key=lambda x: x[1], reverse=True)[:3] for i, (aasqa_code, count) in enumerate(top_metro, 1): aasqa_info = get_aasqa_info(aasqa_code) print(f" {i}. {aasqa_info['region']}: {count} départements ({aasqa_info['organisme']})") print() # Analyse 3: Organismes avec URL atmo vs autres print("3️⃣ Analyse des noms d'organismes:") from atmo_data_wrapper import AASQA_CODES atmo_orgs = [] other_orgs = [] for aasqa_code, aasqa_data in AASQA_CODES.items(): if 'atmo' in aasqa_data['organisme'].lower(): atmo_orgs.append(aasqa_data['organisme']) else: other_orgs.append(aasqa_data['organisme']) print(f" • Organismes 'Atmo': {len(atmo_orgs)} ({len(atmo_orgs)/len(AASQA_CODES)*100:.0f}%)") print(f" • Autres noms: {len(other_orgs)} ({len(other_orgs)/len(AASQA_CODES)*100:.0f}%)") print(f" • Noms alternatifs: {', '.join(other_orgs[:3])}{'...' if len(other_orgs) > 3 else ''}") print() def demo_data_quality_checks(): """Démonstration des vérifications de qualité""" print("🔬 VÉRIFICATIONS DE QUALITÉ DES DONNÉES") print("=" * 55) from atmo_data_wrapper import AASQA_CODES print("1️⃣ Vérification des URLs:") urls_https = 0 urls_http = 0 for aasqa_data in AASQA_CODES.values(): url = aasqa_data['site_web'] if url.startswith('https://'): urls_https += 1 elif url.startswith('http://'): urls_http += 1 print(f" • URLs HTTPS: {urls_https}/{len(AASQA_CODES)} ({urls_https/len(AASQA_CODES)*100:.0f}%)") if urls_http > 0: print(f" ⚠️ URLs HTTP: {urls_http}") else: print(f" ✅ Toutes les URLs sont sécurisées (HTTPS)") print() print("2️⃣ Vérification des codes départementaux:") valid_formats = 0 invalid_formats = [] for aasqa_code, aasqa_data in AASQA_CODES.items(): for dept in aasqa_data['departements']: # Vérifier le format (2 chiffres, 3 chiffres pour DOM-TOM, ou 2A/2B pour Corse) if (dept.isdigit() and len(dept) in [2, 3]) or dept in ['2A', '2B']: valid_formats += 1 else: invalid_formats.append(dept) print(f" • Codes valides: {valid_formats}") if invalid_formats: print(f" ⚠️ Codes invalides: {invalid_formats}") else: print(f" ✅ Tous les codes départementaux sont valides") print() print("3️⃣ Cohérence des descriptions:") consistent = 0 inconsistent = [] for aasqa_code, aasqa_data in AASQA_CODES.items(): expected_desc = f"{aasqa_data['region']} | {aasqa_data['organisme']}" if aasqa_data['description'] == expected_desc: consistent += 1 else: inconsistent.append(aasqa_code) print(f" • Descriptions cohérentes: {consistent}/{len(AASQA_CODES)}") if inconsistent: print(f" ⚠️ Incohérences: {inconsistent}") else: print(f" ✅ Toutes les descriptions sont cohérentes") def main(): """Fonction principale""" print("DÉMONSTRATION DES FONCTIONS UTILITAIRES AASQA AVANCÉES") print("=" * 65) print("Nouvelles analyses et vérifications de qualité des données") print() try: demo_search_functionality() demo_department_statistics() demo_validation_report() demo_comprehensive_statistics() demo_practical_analysis() demo_data_quality_checks() print("=" * 65) print("✅ TOUTES LES ANALYSES TERMINÉES AVEC SUCCÈS") print() print("🎯 Fonctions utilitaires démontrées:") print(" • search_aasqa_by_name(): Recherche textuelle") print(" • get_departments_count(): Comptage par AASQA") print(" • validate_department_coverage(): Validation intégrité") print(" • get_aasqa_statistics(): Statistiques complètes") print(" • Analyses qualité et cohérence des données") print() print("📁 Fichiers concernés:") print(" • constants.py: Données pures (sites web, départements)") print(" • utils.py: Fonctions utilitaires (nouvelle architecture)") except Exception as e: print(f"❌ Erreur lors de l'exécution: {e}") import traceback print("\nDétails de l'erreur:") print(traceback.format_exc()) if __name__ == "__main__": main()