test.
py
import flet as ft
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from datetime import datetime
import json
import asyncio
from typing import Dict, List, Optional
import geopandas as gpd
from [Link] import geodesic
import folium
from io import BytesIO
import base64
# Import des modules personnalisés
from utils.telecom_analysis import TelecomAnalyzer
from [Link] import GeoMarketingAnalyzer
from utils.map_utils import MapGenerator
class SIGTelecomApp:
def __init__(self, page: [Link]):
[Link] = page
[Link] = "SIG Télécom & Géomarketing"
[Link].theme_mode = [Link]
[Link] = 20
[Link].window_width = 1400
[Link].window_height = 900
# Initialisation des analyseurs
self.telecom_analyzer = TelecomAnalyzer()
self.geomarketing_analyzer =
GeoMarketingAnalyzer()
self.map_generator = MapGenerator()
# Données
self.telecom_data = None
self.geo_data = None
self.marketing_data = None
# État de l'application
self.current_map = None
self.selected_region = None
# Initialiser l'interface
self.init_ui()
def init_ui(self):
"""Initialiser l'interface utilisateur"""
# Barre de navigation
self.nav_bar = [Link](
destinations=[
[Link](icon=[Link],
label="Tableau de bord"),
[Link](icon=[Link], label="Carte
SIG"),
[Link](icon=[Link].SIGNAL_CELLULAR_AL
T, label="Analyse Télécom"),
[Link](icon=[Link],
label="Géomarketing"),
[Link](icon=[Link],
label="Rapports"),
],
on_change=self.on_nav_change,
selected_index=0
)
# Contenu principal
self.main_content = [Link](expand=True,
scroll=[Link])
# Barre latérale pour les filtres
[Link] = [Link](
width=300,
padding=20,
bgcolor=[Link].BLUE_GREY_50,
border_radius=10,
content=self.build_sidebar()
)
# Layout principal
[Link](
[Link]([
[Link],
[Link](width=1),
[Link]([self.main_content,
self.nav_bar], expand=True),
], expand=True)
)
# Charger les données et afficher le tableau de
bord
self.load_data()
self.show_dashboard()
def build_sidebar(self):
"""Construire la barre latérale avec les
filtres"""
return [Link]([
[Link]("Filtres", size=20,
weight=[Link]),
[Link](height=20),
# Filtre par région
[Link]("Région:", size=14),
self.region_dropdown = [Link](
options=[[Link]("Toutes les
régions")],
on_change=self.on_region_change,
width=250
),
[Link](height=20),
# Filtre par date
[Link]("Période:", size=14),
self.date_picker = [Link](
first_date=datetime(2023, 1, 1),
last_date=[Link](),
),
[Link](
"Sélectionner la période",
icon=[Link].CALENDAR_MONTH,
on_click=lambda _:
self.date_picker.pick_date(),
width=250
),
[Link](height=20),
# Filtre par indicateur télécom
[Link]("Indicateur Télécom:", size=14),
self.telecom_indicator = [Link](
options=[
[Link]("Couverture
réseau"),
[Link]("Qualité de
service"),
[Link]("Trafic données"),
[Link]("Abonnés"),
],
value="Couverture réseau",
on_change=self.on_indicator_change,
width=250
),
[Link](height=40),
# Boutons d'action
[Link](
"Actualiser les données",
icon=[Link],
on_click=self.refresh_data,
width=250
),
[Link](
"Exporter le rapport",
icon=[Link],
on_click=self.export_report,
width=250,
bgcolor=[Link].GREEN_ACCENT_100
),
])
def load_data(self):
"""Charger les données depuis les fichiers"""
try:
# Charger les données télécom
self.telecom_data = pd.read_csv("data/
telecom_data.csv")
# Charger les données géographiques
self.geo_data = gpd.read_file("data/
[Link]")
# Charger les données de marketing
with open("data/marketing_data.json", "r") as
f:
self.marketing_data = [Link](f)
# Mettre à jour les filtres de région
regions = ["Toutes les régions"] +
list(self.geo_data["nom_region"].unique())
self.region_dropdown.options =
[[Link](r) for r in regions]
self.region_dropdown.value = "Toutes les
régions"
# Mettre à jour les analyseurs
self.telecom_analyzer.set_data(self.telecom_data)
self.geomarketing_analyzer.set_data(self.marketing_data,
self.geo_data)
except Exception as e:
print(f"Erreur lors du chargement des
données: {e}")
def show_dashboard(self):
"""Afficher le tableau de bord"""
self.main_content.[Link]()
# En-tête
self.main_content.[Link](
[Link]([
[Link]([Link], size=40),
[Link]("Tableau de bord SIG Télécom",
size=30, weight=[Link]),
], alignment=[Link])
)
# KPI Cards
kpi_row = [Link]([], spacing=20)
kpis = [
{"title": "Couverture Réseau", "value":
"95%", "icon": [Link].SIGNAL_WIFI_4_BAR, "color":
[Link]},
{"title": "Zones Prioritaires", "value":
"12", "icon": [Link].LOCATION_ON, "color":
[Link]},
{"title": "Clients Potentiels", "value":
"1,245", "icon": [Link], "color":
[Link]},
{"title": "Satisfaction", "value": "4.2/5",
"icon": [Link], "color": [Link]},
]
for kpi in kpis:
kpi_row.[Link](
[Link](
width=200,
height=120,
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]([
[Link](kpi["icon"],
color=kpi["color"], size=30),
[Link](kpi["title"],
size=16, weight=[Link]),
]),
[Link](kpi["value"], size=40,
weight=[Link]),
])
)
)
self.main_content.[Link](kpi_row)
# Graphiques
charts_row = [Link]([], spacing=20, height=400)
# Graphique de couverture
coverage_chart = self.create_coverage_chart()
charts_row.[Link](
[Link](
width=600,
height=400,
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]("Couverture Réseau par
Région", size=18, weight=[Link]),
[Link](src_base64=coverage_chart,
width=550, height=300),
])
)
)
# Graphique de trafic
traffic_chart = self.create_traffic_chart()
charts_row.[Link](
[Link](
width=600,
height=400,
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]("Trafic Données par Type",
size=18, weight=[Link]),
[Link](src_base64=traffic_chart,
width=550, height=300),
])
)
)
self.main_content.[Link](charts_row)
# Carte simplifiée
self.main_content.[Link](
[Link](
height=300,
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]("Carte des Zones
d'Intervention", size=18, weight=[Link]),
[Link]([
[Link](src_base64=self.create_simple_map(), width=800,
height=200),
[Link]([
[Link]("Légende:", size=14,
weight=[Link]),
[Link]([[Link](width=20, height=20,
bgcolor=[Link]), [Link]("Priorité Haute")]),
[Link]([[Link](width=20, height=20,
bgcolor=[Link]), [Link]("Priorité Moyenne")]),
[Link]([[Link](width=20, height=20,
bgcolor=[Link]), [Link]("Priorité Basse")]),
])
])
])
)
)
[Link]()
def show_sig_map(self):
"""Afficher la carte SIG interactive"""
self.main_content.[Link]()
self.main_content.[Link](
[Link]([
[Link]([Link], size=40),
[Link]("Carte SIG Interactive", size=30,
weight=[Link]),
], alignment=[Link])
)
# Générer la carte Folium
m = self.map_generator.create_interactive_map(
self.geo_data,
self.telecom_data,
self.selected_region
)
# Convertir la carte en HTML puis en base64
map_html = m.get_root().render()
map_base64 =
base64.b64encode(map_html.encode()).decode()
# Afficher la carte dans un WebView
self.main_content.[Link](
[Link](
expand=True,
border_radius=10,
shadow=[Link](blur_radius=10),
content=[Link](
"data:text/html;base64," +
map_base64,
width=1000,
height=600,
on_page_started=lambda e:
print("Carte chargée")
)
)
)
# Contrôles de la carte
controls = [Link]([
[Link](
"Zoom sur la sélection",
icon=[Link].ZOOM_IN_MAP,
on_click=self.zoom_to_selection
),
[Link](
"Ajouter une couche",
icon=[Link],
on_click=self.add_layer
),
[Link](
"Exporter la vue",
icon=[Link].SAVE_ALT,
on_click=self.export_map_view
),
], spacing=20)
self.main_content.[Link](controls)
[Link]()
def show_telecom_analysis(self):
"""Afficher l'analyse télécom"""
self.main_content.[Link]()
self.main_content.[Link](
[Link]([
[Link]([Link].SIGNAL_CELLULAR_ALT,
size=40),
[Link]("Analyse Télécom", size=30,
weight=[Link]),
], alignment=[Link])
)
# Analyse de couverture
analysis =
self.telecom_analyzer.analyze_coverage(self.selected_regi
on)
self.main_content.[Link](
[Link](
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link](f"Analyse de couverture:
{self.selected_region or 'Toutes les régions'}",
size=20,
weight=[Link]),
[Link](
columns=[
[Link]([Link]("Indicateur")),
[Link]([Link]("Valeur")),
[Link]([Link]("Tendance")),
],
rows=[
[Link](cells=[
[Link]([Link]("Taux
de couverture")),
[Link]([Link](f"{analysis['coverage_rate']:.1%}")),
[Link]([Link]([Link].TRENDING_UP,
color=[Link])),
]),
[Link](cells=[
[Link]([Link]("Qualité moyenne")),
[Link]([Link](f"{analysis['avg_quality']:.2f}/5")),
[Link]([Link]([Link].TRENDING_FLAT,
color=[Link])),
]),
[Link](cells=[
[Link]([Link]("Zones blanches")),
[Link]([Link](str(analysis['white_zones']))),
[Link]([Link]([Link].TRENDING_DOWN,
color=[Link])),
]),
]
),
])
)
)
# Graphiques d'analyse
charts =
self.telecom_analyzer.create_analysis_charts([Link]
d_region)
for chart_title, chart_base64 in [Link]():
self.main_content.[Link](
[Link](
width=800,
height=300,
padding=20,
margin=[Link](top=20),
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link](chart_title, size=18,
weight=[Link]),
[Link](src_base64=chart_base64,
width=750, height=200),
])
)
)
[Link]()
def show_geomarketing(self):
"""Afficher l'analyse géomarketing"""
self.main_content.[Link]()
self.main_content.[Link](
[Link]([
[Link]([Link], size=40),
[Link]("Analyse Géomarketing", size=30,
weight=[Link]),
], alignment=[Link])
)
# Segmentation géographique
segments =
self.geomarketing_analyzer.geographic_segmentation()
self.main_content.[Link](
[Link](
padding=20,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]("Segmentation des clients",
size=20, weight=[Link]),
[Link]([
[Link](
width=200,
padding=20,
bgcolor=[Link].BLUE_50,
border_radius=10,
content=[Link]([
[Link]("Zone Urbaine",
size=16, weight=[Link]),
[Link](f"{segments['urban']} clients", size=24),
])
),
[Link](
width=200,
padding=20,
bgcolor=[Link].GREEN_50,
border_radius=10,
content=[Link]([
[Link]("Zone
Périurbaine", size=16, weight=[Link]),
[Link](f"{segments['suburban']} clients", size=24),
])
),
[Link](
width=200,
padding=20,
bgcolor=[Link].ORANGE_50,
border_radius=10,
content=[Link]([
[Link]("Zone Rurale",
size=16, weight=[Link]),
[Link](f"{segments['rural']} clients", size=24),
])
),
], spacing=20)
])
)
)
# Analyse de potentiel
potential_analysis =
self.geomarketing_analyzer.potential_analysis()
self.main_content.[Link](
[Link](
padding=20,
margin=[Link](top=20),
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link]("Analyse de potentiel
commercial", size=20, weight=[Link]),
[Link](
columns=[
[Link]([Link]("Zone")),
[Link]([Link]("Potentiel")),
[Link]([Link]("Recommandation")),
],
rows=[
[Link](cells=[
[Link]([Link](zone)),
[Link]([Link](f"{data['potential']:.1%}")),
[Link]([Link](data['recommendation'])),
]) for zone, data in
potential_analysis.items()
]
),
])
)
)
[Link]()
def show_reports(self):
"""Afficher les rapports"""
self.main_content.[Link]()
self.main_content.[Link](
[Link]([
[Link]([Link], size=40),
[Link]("Rapports et Analyses", size=30,
weight=[Link]),
], alignment=[Link])
)
# Générer le rapport
report = self.generate_comprehensive_report()
self.main_content.[Link](
[Link](
padding=30,
bgcolor=[Link],
border_radius=10,
shadow=[Link](blur_radius=5),
content=[Link]([
[Link](f"Rapport:
{[Link]().strftime('%d/%m/%Y')}",
size=24,
weight=[Link]),
[Link](height=20),
[Link]("Synthèse Télécom:", size=18,
weight=[Link]),
[Link](report['telecom_summary']),
[Link](height=20),
[Link]("Opportunités Géomarketing:",
size=18, weight=[Link]),
[Link](report['marketing_opportunities']),
[Link](height=20),
[Link]("Recommandations:", size=18,
weight=[Link]),
[Link]([
[Link](title=[Link](rec))
for rec in report['recommendations']
], height=200),
])
)
)
[Link]()
def create_coverage_chart(self):
"""Créer un graphique de couverture"""
import [Link] as plt
import io
if self.telecom_data is not None:
regions =
self.telecom_data['region'].unique()[:5]
coverage =
self.telecom_data.groupby('region')['coverage'].mean()
[:5]
fig, ax = [Link](figsize=(8, 4))
bars = [Link](regions, coverage * 100)
# Colorer les barres
for bar in bars:
bar.set_color('#2196F3')
ax.set_ylabel('Couverture (%)')
ax.set_title('Couverture réseau par région')
[Link](rotation=45)
plt.tight_layout()
# Convertir en base64
buf = [Link]()
[Link](buf, format='png', dpi=100)
[Link]()
[Link](0)
return base64.b64encode([Link]()).decode()
return ""
def create_traffic_chart(self):
"""Créer un graphique de trafic"""
import [Link] as plt
import io
# Données simulées
traffic_types = ['Voix', 'Données 4G', 'Données
5G', 'SMS']
traffic_volume = [35, 45, 15, 5]
fig, ax = [Link](figsize=(8, 4))
[Link](traffic_volume, labels=traffic_types,
autopct='%1.1f%%',
colors=['#FF6384', '#36A2EB', '#FFCE56',
'#4BC0C0'])
ax.set_title('Répartition du trafic par type')
# Convertir en base64
buf = [Link]()
[Link](buf, format='png', dpi=100)
[Link]()
[Link](0)
return base64.b64encode([Link]()).decode()
def create_simple_map(self):
"""Créer une carte simplifiée"""
import [Link] as plt
import io
# Carte simplifiée (à remplacer par une vraie
carte)
fig, ax = [Link](figsize=(12, 6))
# Simuler des régions
regions = ['Nord', 'Sud', 'Est', 'Ouest',
'Centre']
x = [1, 5, 3, 2, 4]
y = [2, 1, 4, 3, 2]
sizes = [100, 150, 80, 120, 90]
colors = ['red', 'orange', 'green', 'orange',
'red']
scatter = [Link](x, y, s=[s*10 for s in
sizes], c=colors, alpha=0.6)
for i, region in enumerate(regions):
[Link](region, (x[i], y[i]),
fontsize=12)
ax.set_title('Carte des zones d\'intervention')
ax.set_xlim(0, 6)
ax.set_ylim(0, 5)
[Link](True, alpha=0.3)
# Convertir en base64
buf = [Link]()
[Link](buf, format='png', dpi=100)
[Link]()
[Link](0)
return base64.b64encode([Link]()).decode()
def generate_comprehensive_report(self):
"""Générer un rapport complet"""
return {
'telecom_summary': """
- **Taux de couverture global**: 94.5%
- **Qualité moyenne du service**: 4.2/5
- **Zones à améliorer**: 3 régions
identifiées
- **Trafic total**: 2.4 To/jour
""",
'marketing_opportunities': """
- **Zone Nord**: Fort potentiel résidentiel
(+15% prévu)
- **Zone Sud**: Développement commercial en
cours
- **Zone Est**: Nouvelles zones industrielles
- **Zone Ouest**: Tourisme numérique en
croissance
""",
'recommendations': [
"Renforcer la couverture 5G dans le
centre-ville",
"Développer des offres commerciales pour
les zones rurales",
"Implémenter des capteurs IoT pour le
suivi en temps réel",
"Créer des partenariats avec les
collectivités locales"
]
}
def on_nav_change(self, e):
"""Gérer le changement de navigation"""
nav_index = [Link].selected_index
if nav_index == 0:
self.show_dashboard()
elif nav_index == 1:
self.show_sig_map()
elif nav_index == 2:
self.show_telecom_analysis()
elif nav_index == 3:
self.show_geomarketing()
elif nav_index == 4:
self.show_reports()
def on_region_change(self, e):
"""Gérer le changement de région"""
self.selected_region = [Link] if
[Link] != "Toutes les régions" else None
# Actualiser l'affichage en fonction de la vue
actuelle
if self.nav_bar.selected_index == 0:
self.show_dashboard()
elif self.nav_bar.selected_index == 1:
self.show_sig_map()
elif self.nav_bar.selected_index == 2:
self.show_telecom_analysis()
def on_indicator_change(self, e):
"""Gérer le changement d'indicateur"""
# Actualiser les visualisations
if self.nav_bar.selected_index == 0:
self.show_dashboard()
def refresh_data(self, e):
"""Actualiser les données"""
self.load_data()
# Montrer une notification
[Link].show_snack_bar(
[Link](
content=[Link]("Données actualisées avec
succès!"),
action="OK"
)
)
self.show_dashboard()
def export_report(self, e):
"""Exporter le rapport"""
# Simulation d'export
[Link].show_snack_bar(
[Link](
content=[Link]("Rapport exporté en
PDF"),
action="OK"
)
)
def zoom_to_selection(self, e):
"""Zoomer sur la sélection"""
if self.selected_region:
[Link].show_snack_bar(
[Link](
content=[Link](f"Zoom sur
{self.selected_region}"),
action="OK"
)
)
def add_layer(self, e):
"""Ajouter une couche à la carte"""
# Ouvrir un dialogue pour choisir une couche
[Link] = [Link](
title=[Link]("Ajouter une couche"),
content=[Link]([
[Link]("Sélectionnez une couche à
ajouter:"),
[Link](
options=[
[Link]("Points
d'accès"),
[Link]("Antennes"),
[Link]("Zones
commerciales"),
[Link]("Démographie"),
]
)
]),
actions=[
[Link]("Annuler",
on_click=self.close_dialog),
[Link]("Ajouter",
on_click=self.close_dialog),
]
)
[Link] = True
[Link]()
def export_map_view(self, e):
"""Exporter la vue de la carte"""
[Link].show_snack_bar(
[Link](
content=[Link]("Carte exportée en PNG"),
action="OK"
)
)
def close_dialog(self, e):
"""Fermer le dialogue"""
[Link] = False
[Link]()
# Modules personnalisés
# utils/telecom_analysis.py
"""
class TelecomAnalyzer:
def __init__(self):
[Link] = None
def set_data(self, data):
[Link] = data
def analyze_coverage(self, region=None):
# Analyse de couverture réseau
pass
def create_analysis_charts(self, region=None):
# Créer des graphiques d'analyse
pass
"""
# utils/[Link]
"""
class GeoMarketingAnalyzer:
def __init__(self):
self.marketing_data = None
self.geo_data = None
def set_data(self, marketing_data, geo_data):
self.marketing_data = marketing_data
self.geo_data = geo_data
def geographic_segmentation(self):
# Segmentation géographique
pass
def potential_analysis(self):
# Analyse de potentiel commercial
pass
"""
# utils/map_utils.py
"""
class MapGenerator:
def create_interactive_map(self, geo_data,
telecom_data, selected_region=None):
# Créer une carte interactive Folium
pass
"""
def main(page: [Link]):
app = SIGTelecomApp(page)
if __name__ == "__main__":
[Link](target=main)