From e2d3311cd1ad8657042e518237488800cd3b0641 Mon Sep 17 00:00:00 2001 From: kevin Date: Thu, 12 Dec 2024 23:39:18 +0100 Subject: [PATCH] Modularizacion del proyecto mas implementacion Implementacion de vista a tiempo real de ciertos recursos, Rastrear una ip, Observar las ip de una wifi a tiempo real. --- MainController.py | 107 ++++++++++++ MainView.py | 102 +++++++++++ __pycache__/MainController.cpython-313.pyc | Bin 0 -> 9518 bytes __pycache__/MainView.cpython-313.pyc | Bin 0 -> 7292 bytes main.py | 160 +----------------- models/NetworkingScanner.py | 25 +++ models/SystemStats.py | 39 +++++ .../NetworkingScanner.cpython-313.pyc | Bin 0 -> 1884 bytes .../__pycache__/SystemStats.cpython-313.pyc | Bin 0 -> 2542 bytes prueba1.py | 158 +++++++++++++++++ pruebas.py | 48 +++--- 11 files changed, 468 insertions(+), 171 deletions(-) create mode 100644 MainController.py create mode 100644 MainView.py create mode 100644 __pycache__/MainController.cpython-313.pyc create mode 100644 __pycache__/MainView.cpython-313.pyc create mode 100644 models/NetworkingScanner.py create mode 100644 models/SystemStats.py create mode 100644 models/__pycache__/NetworkingScanner.cpython-313.pyc create mode 100644 models/__pycache__/SystemStats.cpython-313.pyc create mode 100644 prueba1.py diff --git a/MainController.py b/MainController.py new file mode 100644 index 0000000..226d7f4 --- /dev/null +++ b/MainController.py @@ -0,0 +1,107 @@ +import threading +from models.SystemStats import SystemStats +from MainView import MainView +from models.NetworkingScanner import NetworkScanner +import tkinter as tk +import time +import datetime + + +class MainController: + def __init__(self, view: MainView): + self.view = view + self.connect_events() + self.start_system_updates() + + def connect_events(self): + """Conecta los eventos de la vista con :las funciones del controlador.""" + self.view.button_track_ip.config(command=self.handle_track_ip) + self.view.button_scan_network.config(command=self.start_network_scan_thread) + + def start_network_scan_thread(self): + """Inicia un hilo para escanear la red continuamente cada 5 segundos.""" + def scan_network_periodically(): + network_range = NetworkScanner.get_network_range() + while True: + print("Scanning....") + devices = NetworkScanner.scan_network(network_range) + self.display_network_scan_results(devices) + time.sleep(1) # Escanear cada 5 segundos + + # Inicia un hilo para el escaneo continuo + threading.Thread(target=scan_network_periodically, daemon=True).start() + + def handle_track_ip(self): + """Maneja el evento de rastrear una IP.""" + ip = self.view.entry_ip.get() # Obtener la IP ingresada + if not ip: + self.view.text_output.insert(tk.END, "Por favor, introduce una IP válida.\n") + return + + # Ejecutar fetch_ip_data en un hilo + def fetch_ip_data(): + try: + result = SystemStats.track_ip(ip) # Llamar a la función con la IP + if "error" in result: + self.view.text_output.insert(tk.END, f"Error: {result['error']}\n") + else: + self.display_ip_data(result) + except Exception as e: + self.view.text_output.insert(tk.END, f"Error al rastrear la IP: {e}\n") + + threading.Thread(target=fetch_ip_data, daemon=True).start() + + + def display_network_scan_results(self, devices): + """Muestra los resultados del escaneo en la interfaz.""" + # Limpiar el texto anterior y mostrar los nuevos resultados + self.view.text_network_scan.delete('1.0', tk.END) + self.view.text_network_scan.insert(tk.END, "Dispositivos encontrados:\n") + for device in devices: + self.view.text_network_scan.insert(tk.END, f"IP: {device['ip']}, MAC: {device['mac']}\n") + + def display_ip_data(self, data): + """Muestra la información de la IP en el área de texto.""" + self.view.text_output.insert(tk.END, f"IP: {data['ip']}\n") + self.view.text_output.insert(tk.END, f"Tipo: {data['type']}\n") + self.view.text_output.insert(tk.END, f"País: {data['country']} ({data['country_code']})\n") + self.view.text_output.insert(tk.END, f"Región: {data['region']} ({data['region_code']})\n") + self.view.text_output.insert(tk.END, f"Ciudad: {data['city']}\n") + self.view.text_output.insert(tk.END, f"Latitud: {data['latitude']}\n") + self.view.text_output.insert(tk.END, f"Longitud: {data['longitude']}\n") + self.view.text_output.insert(tk.END, f"Mapa: https://www.google.com/maps/@{data['latitude']},{data['longitude']},8z\n") + self.view.text_output.insert(tk.END, "=============================================\n") + + def start_system_updates(self): + """Inicia las actualizaciones periódicas del sistema.""" + threading.Thread(target=self.update_system_stats, daemon=True).start() + self.update_time() + + def update_time(self): + """Actualiza el reloj en la barra de estado.""" + now = datetime.datetime.now() + time_str = now.strftime("%H:%M:%S") + date_str = now.strftime("%Y-%m-%d") + day_of_week = now.strftime("%A") + self.view.label_fecha_hora.config(text=f"{day_of_week}, {date_str} - {time_str}") + self.view.root.after(1000, self.update_time) # Actualizar cada segundo + + def update_system_stats(self): + """Actualiza las estadísticas del sistema periódicamente en un hilo.""" + while True: + # Obtener estadísticas del sistema + cpu_usage = SystemStats.get_cpu_usage() + memory_usage = SystemStats.get_memory_usage() + bytes_sent, bytes_recv = SystemStats.get_network_usage() + + # Actualizar etiquetas en el hilo principal + self.view.root.after(0, self.view.label_cpu.config, {"text": f"Uso CPU: {cpu_usage:.2f}%"}) + self.view.root.after(0, self.view.label_uso_memoria.config, {"text": f"Uso RAM: {memory_usage:.2f}%"}) + self.view.root.after(0, self.view.label_bytes_sent.config, {"text": f"Subida: {bytes_sent / 1024:.2f} KB/s"}) + self.view.root.after(0, self.view.label_bytes_recv.config, {"text": f"Descarga: {bytes_recv / 1024:.2f} KB/s"}) + + time.sleep(1) # Esperar 1 segundo antes de actualizar nuevamente + + + + diff --git a/MainView.py b/MainView.py new file mode 100644 index 0000000..27dd48a --- /dev/null +++ b/MainView.py @@ -0,0 +1,102 @@ +import tkinter as tk # Importar Tkinter para la interfaz gráfica +from tkinter import ttk, scrolledtext # Importar widgets específicos de Tkinter + + +class MainView: + def __init__(self, root): + self.root = root + self.root.title("Ventana Responsive") + self.root.geometry("1000x700") # Tamaño inicial + + # Configuración de la ventana principal + self.root.columnconfigure(1, weight=1) # Columna central ajustable + self.root.rowconfigure(0, weight=1) # Fila principal ajustable + self.root.rowconfigure(1, weight=0) # Fila inferior (barra de estado) + + # Crear frames principales + self.frame_left = tk.Frame(self.root, bg="lightblue", width=200) + self.frame_center = tk.Frame(self.root, bg="white", height=400, width=600) + self.frame_bottom = tk.Frame(self.root, bg="lightgray", height=50) + self.frame_right = tk.Frame(self.root, bg="red", width=200) + + # Configurar posiciones en el grid + self.frame_left.grid(row=0, column=0, sticky="ns") + self.frame_center.grid(row=0, column=1, padx=10, pady=10, sticky="nsew") + self.frame_right.grid(row=0, column=2, sticky="ns") + self.frame_bottom.grid(row=1, column=0, columnspan=3, sticky="ew") + + # Configurar tamaños fijos + self.frame_left.grid_propagate(False) + self.frame_center.grid_propagate(False) + self.frame_bottom.grid_propagate(False) + self.frame_right.grid_propagate(False) + + # Crear el notebook dentro del frame central + self.create_tabs() + + # Crear barra de estado en el frame inferior + self.create_status_bar() + + def create_tabs(self): + """Crea las solapas dentro del notebook.""" + self.notebook = ttk.Notebook(self.frame_center, height=800, width=800) + self.notebook.pack(padx=10, pady=10) + + # Solapa 1: IP Tracker + tab1 = ttk.Frame(self.notebook) + self.notebook.add(tab1, text="IP Tracker") + self.create_tracker_ui(tab1) + + # Solapa 2: Escaneo de red + tab2 = ttk.Frame(self.notebook) + self.notebook.add(tab2, text="Escaneo de Red") + self.create_network_scan_ui(tab2) + + # Solapas 3-5: Vacías + for i in range(3, 6): + tab = ttk.Frame(self.notebook) + self.notebook.add(tab, text=f"Solapa {i}") + label = ttk.Label(tab, text=f"Contenido de la Solapa {i}") + label.pack(pady=10) + + def create_tracker_ui(self, tab): + """Crea la interfaz de usuario para el rastreador de IP en la solapa 1.""" + label_ip = ttk.Label(tab, text="Introduce la IP para rastrear:") + label_ip.pack(pady=5) + + self.entry_ip = ttk.Entry(tab, width=40) + self.entry_ip.pack(pady=5) + + self.text_output = scrolledtext.ScrolledText(tab, wrap=tk.WORD, height=10, width=60) + self.text_output.pack(fill="both", expand=True, pady=10) + + self.button_track_ip = ttk.Button(tab, text="Rastrear IP") + self.button_track_ip.pack(pady=5) + + def create_network_scan_ui(self, tab): + """Crea la interfaz de usuario para el escaneo de red en la Solapa 2.""" + label = ttk.Label(tab, text="Escaneo de dispositivos en la red:") + label.pack(pady=5) + + self.text_network_scan = scrolledtext.ScrolledText(tab, wrap=tk.WORD, height=20, width=80) + self.text_network_scan.pack(fill="both", expand=True, pady=10) + + # Botón para iniciar el escaneo + self.button_scan_network = ttk.Button(tab, text="Iniciar Escaneo") + self.button_scan_network.pack(pady=5) + + def create_status_bar(self): + """Crea una barra de estado en la parte inferior.""" + self.label_cpu = tk.Label(self.frame_bottom, text="Uso CPU: 0%", bg="orange", anchor="w", width=20) + self.label_bytes_recv = tk.Label(self.frame_bottom, text="Descarga: 0 KB/s", bg="blue", anchor="w", width=20) + self.label_bytes_sent = tk.Label(self.frame_bottom, text="Subida: 0 KB/s", bg="cyan", anchor="w", width=20) + self.label_uso_memoria = tk.Label(self.frame_bottom, text="Uso RAM: 0%", bg="pink", anchor="w", width=20) + self.label_fecha_hora = tk.Label( + self.frame_bottom, text="Hilo fecha-hora", font=("Helvetica", 14), fg="blue", relief="sunken", anchor="w", width=20 + ) + + self.label_cpu.pack(side="left", fill="x", expand=True) + self.label_bytes_recv.pack(side="left", fill="x", expand=True) + self.label_bytes_sent.pack(side="left", fill="x", expand=True) + self.label_uso_memoria.pack(side="left", fill="x", expand=True) + self.label_fecha_hora.pack(side="right", fill="x", expand=True) diff --git a/__pycache__/MainController.cpython-313.pyc b/__pycache__/MainController.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89b16593c8afa48a7d89d9841621119050b84304 GIT binary patch literal 9518 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 literal 0 HcmV?d00001 diff --git a/__pycache__/MainView.cpython-313.pyc b/__pycache__/MainView.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80cee7b67abec4af4c252f9d6ee4ce8a0f238dfe GIT binary patch literal 7292 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 WJJa+Jrt806!QmKoJY(pCvi=W~F_cCC literal 0 HcmV?d00001 diff --git a/main.py b/main.py index af6f8e5..9fe5a33 100644 --- a/main.py +++ b/main.py @@ -1,153 +1,9 @@ -import tkinter as tk -from tkinter import Menu # Importar el widget Menu -from tkinter import ttk # Importar el widget ttk -import threading -import time -import datetime -import psutil +import tkinter as tk # Importar Tkinter para la interfaz gráfica +from MainView import MainView # Importar la clase de la vista +from MainController import MainController # Importar la clase del controlador -def update_memoria(interval): - while True: - # Obtener el porcentaje de memoria usada - memory_usage = psutil.virtual_memory().percent - laber_text = "Uso RAM: " +f"{memory_usage:.2f}%"; - label_uso_memoria.after(1000,interval.config, {"text": laber_text}) - time.sleep(1) - - -def update_time(status_bar): - """Función que actualiza la hora y el día de la semana en un label""" - while True: - # Obtener la fecha y hora actual - now = datetime.datetime.now() - day_of_week = now.strftime("%A") # Día de la semana - time_str = now.strftime("%H:%M:%S") # Hora en formato HH:MM:SS - date_str = now.strftime("%Y-%m-%d") # Fecha en formato YYYY-MM-DD - label_text = f"{day_of_week}, {date_str} - {time_str}" - - # Actualizar el label (debemos usar `after` para asegurarnos que se actualice en el hilo principal de Tkinter) - label_fecha_hora.after(1000, status_bar.config, {"text": label_text}) - - # Espera 1 segundo antes de actualizar de nuevo - time.sleep(1) - - -# Crear la ventana principal -root = tk.Tk() -root.title("Ventana Responsive") -root.geometry("1000x700") # Tamaño inicial - -# Configurar la ventana principal para que sea responsive -root.columnconfigure(0, weight=0) # Columna izquierda, tamaño fijo -root.columnconfigure(1, weight=1) # Columna central, tamaño variable -root.columnconfigure(2, weight=0) # Columna derecha, tamaño fijo -root.rowconfigure(0, weight=1) # Fila principal, tamaño variable -root.rowconfigure(1, weight=0) # Barra de estado, tamaño fijo - -# Crear el menú superior -menu_bar = Menu(root) - -file_menu = Menu(menu_bar, tearoff=0) -file_menu.add_command(label="Nuevo") -file_menu.add_command(label="Abrir") -file_menu.add_separator() -file_menu.add_command(label="Salir", command=root.quit) - -edit_menu = Menu(menu_bar, tearoff=0) -edit_menu.add_command(label="Copiar") -edit_menu.add_command(label="Pegar") - -help_menu = Menu(menu_bar, tearoff=0) -help_menu.add_command(label="Acerca de") - -menu_bar.add_cascade(label="Archivo", menu=file_menu) -menu_bar.add_cascade(label="Editar", menu=edit_menu) -menu_bar.add_cascade(label="Ayuda", menu=help_menu) - -root.config(menu=menu_bar) - -# Crear los frames laterales y el central -frame_izquierdo = tk.Frame(root, bg="lightblue", width=200) -frame_central = tk.Frame(root, bg="white") -frame_derecho = tk.Frame(root, bg="lightgreen", width=200) - -# Colocar los frames laterales y el central -frame_izquierdo.grid(row=0, column=0, sticky="ns") -frame_central.grid(row=0, column=1, sticky="nsew") -frame_derecho.grid(row=0, column=2, sticky="ns") - -# Configurar los tamaños fijos de los frames laterales -frame_izquierdo.grid_propagate(False) -frame_derecho.grid_propagate(False) - -# Dividir el frame central en dos partes (superior variable e inferior fija) -frame_central.rowconfigure(0, weight=1) # Parte superior, tamaño variable -frame_central.rowconfigure(1, weight=0) # Parte inferior, tamaño fijo -frame_central.columnconfigure(0, weight=1) # Ocupa toda la anchura - -# Crear subframes dentro del frame central -frame_superior = tk.Frame(frame_central, bg="lightyellow") -frame_inferior = tk.Frame(frame_central, bg="lightgray", height=100) - -# Colocar los subframes dentro del frame central -frame_superior.grid(row=0, column=0, sticky="nsew") -frame_inferior.grid(row=1, column=0, sticky="ew") - -# Fijar el tamaño de la parte inferior -frame_inferior.grid_propagate(False) - -# Crear la barra de estado -barra_estado = tk.Label(root, text="Barra de estado", bg="lightgray", anchor="w") -barra_estado.grid(row=1, column=0, columnspan=3, sticky="ew") - -# Notebook para las pestañas - -style = ttk.Style() -style.configure("CustomNotebook.TNotebook.Tab", font=("Arial", 12, "bold")) -notebook = ttk.Notebook(frame_superior, style="CustomNotebook.TNotebook") -notebook.pack(fill="both", expand=True) - - -# Crear cinco solapas -for i in range(1, 6): - tab = ttk.Frame(notebook) - - notebook.add(tab, text=f"Solapa {i}", padding=4) - # Añadir un Label en cada solapa para diferenciarla - label = ttk.Label(tab, text=f"Contenido de la Solapa {i}") - label.pack(pady=10) - -# Barra de estado -# Dividir la barra de estado en 4 labels - - -# Usar pack para alinear los labels horizontalmente - - -label_1 = tk.Label(barra_estado, text="Estado 1", bg="green", anchor="w", width=20) -label_2 = tk.Label(barra_estado, text="Estado 2", bg="blue", anchor="w", width=20) -label_3 = tk.Label(barra_estado, text="Estado 3", bg="cyan", anchor="w", width=20) -label_uso_memoria = tk.Label(barra_estado, text="Estado 4", bg="pink", anchor="w", width=20) -label_fecha_hora = tk.Label(barra_estado, text="Hilo fecha-hora", font=("Helvetica", 14), bd=1, fg="blue", relief="sunken", anchor="w", width=20, padx=10) - -label_1.pack(side="left", fill="x", expand=True) -label_2.pack(side="left", fill="x", expand=True) -label_3.pack(side="left", fill="x", expand=True) -label_uso_memoria.pack(side="left", fill="x", expand=True) -label_fecha_hora.pack(side="right", fill="x", expand=True) -# barra_estado.grid(row=1, column=0, columnspan=3, sticky="ew") - - -update_thread = threading.Thread(target=update_time, args=(label_fecha_hora,)) -update_thread.daemon = True # Hacemos el hilo un demonio para que termine con la app -update_thread.start() - -update_thread_memoria = threading.Thread(target=update_memoria, args=(label_uso_memoria,)) -update_thread_memoria.daemon = True -update_thread_memoria.start() - -#Uso en memoria - - -# Ejecución de la aplicación -root.mainloop() \ No newline at end of file +if __name__ == "__main__": + root = tk.Tk() + view = MainView(root) + controller = MainController(view) + root.mainloop() \ No newline at end of file diff --git a/models/NetworkingScanner.py b/models/NetworkingScanner.py new file mode 100644 index 0000000..9d766cc --- /dev/null +++ b/models/NetworkingScanner.py @@ -0,0 +1,25 @@ +import socket +import ipaddress +import nmap + +class NetworkScanner: + @staticmethod + def get_network_range(): + """Obtiene el rango de red basado en la IP local.""" + hostname = socket.gethostname() + local_ip = socket.gethostbyname(hostname) + network = ipaddress.ip_network(f"{local_ip}/24", strict=False) + print(str(network)) + return str(network) + + @staticmethod + def scan_network(ip_range): + """Realiza un escaneo de red y devuelve los dispositivos detectados.""" + nm = nmap.PortScanner() + nm.scan(hosts=ip_range, arguments='-sn') + devices = [] + for host in nm.all_hosts(): + if nm[host].state() == "up": + mac = nm[host]['addresses'].get('mac', 'No MAC address found') + devices.append({'ip': nm[host]['addresses']['ipv4'], 'mac': mac}) + return devices diff --git a/models/SystemStats.py b/models/SystemStats.py new file mode 100644 index 0000000..039f1c1 --- /dev/null +++ b/models/SystemStats.py @@ -0,0 +1,39 @@ +import psutil +import time +import requests + +class SystemStats: + @staticmethod + def get_memory_usage(): + """Obtiene el porcentaje de uso de memoria.""" + return psutil.virtual_memory().percent + + @staticmethod + def get_cpu_usage(): + """Obtiene el porcentaje de uso de CPU.""" + return psutil.cpu_percent(interval=0) + + @staticmethod + def get_network_usage(): + """Calcula la velocidad de subida y bajada de la red.""" + net_io_start = psutil.net_io_counters() + time.sleep(1) # Esperar 1 segundo para medir el uso + net_io_end = psutil.net_io_counters() + + # Calcular velocidades + bytes_sent_per_sec = net_io_end.bytes_sent - net_io_start.bytes_sent + bytes_recv_per_sec = net_io_end.bytes_recv - net_io_start.bytes_recv + + return bytes_sent_per_sec, bytes_recv_per_sec + + @staticmethod + def track_ip(ip): + """Obtiene información de una IP mediante la API ipwho.is.""" + try: + response = requests.get(f"http://ipwho.is/{ip}") + data = response.json() + if not data.get("success", False): + return {"error": data.get("message", "No se encontró información.")} + return data + except requests.exceptions.RequestException as e: + return {"error": str(e)} diff --git a/models/__pycache__/NetworkingScanner.cpython-313.pyc b/models/__pycache__/NetworkingScanner.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2dcf5f27624b6e00cc505f9e2fb797ea79118f6 GIT binary patch literal 1884 zcmb7EO>7fK6rTOFHwjLH9g>ukGNL8HLQVJyqR^@m3ZNp030_%3ilx`;Z+5*Qq3xk_c=P_>%$x5`HYH4RwsxA&B*2PT1mDD6(vSajb)^|`|UzxtT6ncabOnl57S`Bc8U`8r<$>B~V zz=UGo!Iu`WAGnS`y`s&Wn7x=+M2d&ZbHjWZxWK(hLNQP!;c~!3>ePtH^n|5bk=W~HB&)HYyWMO%iIN@kquCAGK>oO+F&ShUHzAm)RcZT-f`|QD;dv`X54nCRvb!e(HI{t9^ zo7?Ttqno2M?a`UzW>9;_T=2pbM1o*zYSk| znMV8G-ZIhfSZk2&gQI+h3VBnQwk^L9+ZO${4TIb8CBMhEKWR9A&oX4&H$28e-=l;E z(k%Puxi$GCRag#^u{;p5&$eTW?S$}uEj2>IZJQmH4zgs_HYR`Rh{$&GBS7w=j?Sd)LhD zh9;sC>Y<9NN-eD-klF)1mEMr}3xI#XPE2%v1d2V@0Z0ooine{a45{=-}Q$@#Ttu_jT9TRL=c z#?rBY6S$P9m_);drOx9-5hrYFvR@gOO`@xrl;DIa)VB1Jvui;omaUc)*S6?{E7%SE z5jEKK&PUp*LY`tm3)k?1ZWJyW_#Dv}aAAUKM7Ll%voJn6eqo{@W3r%Yx;bIwaIr8= z%z3O?=iQ*PS;Qq;XemafvgmZrVar=qv8g(TomW~t+N~kj4&4Xj7WyNEy7$(lkAcTm2xZmIxss|SmtE@Ee>iaEG2iU<@j_yL)bZ`I7ieC3$j;B zDV~Hu<#cKlTk$GM7^vN?kuGM7vc#CZne)E(oVQFY8`=kCE8(G4Y3TmZnv|}J>6epb ziMq-D3e3*Q`tUZ;l`TN!SdrTXTqrKfHI<3~4N`;4b2+hXDiHH%J8c?jWbhE-Hh>qS zAYvP>8zFr7>Ki;97r%6DTrFvKNln1FfJ>&P7u6zzJhf+lO)Ms6)Oi&cP=O1<#mqC7 zQ!3OvFv);J(M?4&ZFZE@30Qg=J3(5)xZ*@+7A;H_3Kz=f3Dy=;0jJB0qn1j*=1JHn zI(weSFeE^*=IdCjucNH?2^dXq>}KGAS#Fr*ng@{nc7VKK?uKw$1mc1uK2VRPS7Yh5 z*ywWChS>FGGxddoe(7=xPkhwhCg^u$+qFkJ?S=z=HI{7@G zV=J@`nSb8m4|%p?FG6zQKm3Do$bS-!z!lE}ZiZTSyAATULuweQF~F)I2d=RD>5jbM zXLE$3{2-FUhA<{1z5gsXi_QpxXqHQf_DKlvJBx12nxw31`jdx-+oTOOF*yxQx~QuF zLWa|^>B)p%xpCFZ=rps`eburmr$$G8&8QQmwx(f9-*QBe%Fj1|R+CDN55vQ7wz; zGdAlwO4|cM0?eNgc5Uc1kk8P1aQAOK9~^B6D70sjahoD=OqbcxWjtLZc*4^Gw;6Z+ zI)WpvuE7J>e683Lses!b31A+P5k}nA+nzM>bh8HUkT=1F^#>XU0@dZXrzrXqbv{MX OpMha+