diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..11e2ff5 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +TELEGRAM_BOT_TOKEN= +MAILJET_API_KEY= +MAILJET_SECRET_KEY= +MAILJET_URL= +EMAIL_FROM= +MAILJET_FROM_NAME= +DOMAIN= +API_KEY_GEMINI= \ No newline at end of file diff --git a/Leer.txt b/Leer.txt new file mode 100644 index 0000000..fa0deb3 --- /dev/null +++ b/Leer.txt @@ -0,0 +1,11 @@ +developers +https://developers.facebook.com/ + +Url para verificar del postman : + +https://www.postman.com/meta/whatsapp-business-platform/request/glfiyeg/send-reply-to-sticker-message-by-id?tab=auth + +twiilo + +https://pages.twilio.com/twilio-brand-sales-spa-latam-2?utm_source=google&utm_medium=cpc&utm_term=twilio&utm_campaign=G_S_LATAM_Brand_Twilio_Spanish&cq_plac=&cq_net=g&cq_pos=&cq_med=&cq_plt=gp&gad_source=1&gad_campaignid=14124383694&gbraid=0AAAAADcHgwURen2eGQVVBQhLnfsJOUonY&gclid=CjwKCAjwyb3DBhBlEiwAqZLe5LyfSVi6XxbjAna0FL4exD4OytnnCvX4owikR1J_XH1h4ivSDzdQiRoC07gQAvD_BwE + diff --git "a/Valeria_Qui\303\261oneztarea2.py" "b/Valeria_Qui\303\261oneztarea2.py" new file mode 100644 index 0000000..63cc0d9 --- /dev/null +++ "b/Valeria_Qui\303\261oneztarea2.py" @@ -0,0 +1,78 @@ +# clase 2-Estructuras y POO +Valeria Beatriz Quiñonez Rodriguez +# Ejercicio 1: Objetos +# Definimos la clase Laptop +class Laptop: + def __init__(self, marca, modelo, año, color, almacenamiento, memoria_ram=8): + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + self.almacenamiento = almacenamiento + self.memoria_ram = memoria_ram + self.estado = "apagado" + + def encender(self): + self.estado = "encendido" + print(f"La laptop {self.marca} {self.modelo} está {self.estado}.") + + def apagar(self): + self.estado = "apagado" + print(f"La laptop {self.marca} {self.modelo} está {self.estado}.") + def reiniciar(self): + if self.estado == "encendido": + print(f"La laptop {self.marca} {self.modelo} se está reiniciando.") + else: + print(f"No se puede reiniciar la laptop {self.marca} {self.modelo} porque está apagada.") +#Ejercicio 2: Listas y Diccionarios +#Lista con tus 3 peliculas favoritas +peliculas_favoritas = ["Legalmente Rubia", "Rasputia", "Shrek"] +#Imprimir lista +print("Mis películas favoritas son:") +for pelicula in peliculas_favoritas: + print(f"- {pelicula}") + #Diccionario con mis datos + mi_info = { + "nombre": "Valeria ", + "edad": 17, + "genero": "Femenino" + } + #Imprimir diccionario +print("\nMis datos:") +for clave, valor in mi_info.items(): + print(f"{clave.capitalize()}: {valor}") +#Ejercicio 3: Trivia con POO +class Pregunta: + def __init__(self, pregunta, respuesta_correcta, respuestas_incorrectas): + self.pregunta = pregunta + self.respuesta_correcta = respuesta_correcta + self.respuestas_incorrectas = respuestas_incorrectas + def mostrar_pregunta(self): + print(f"Pregunta: {self.pregunta}") + print("Respuestas posibles:") + for i, respuesta in enumerate(self.respuestas_incorrectas, start=1): + print(f"{i}. {respuesta}") + print(f"Respuesta correcta: {self.respuesta_correcta}") + print("¿Cuál de los siguientes son factores predisponentes para los cálculos de colesterol?:") + print("1. Fibrosis quística") + print("2. Hemólisis crónica") + print("3. Cirrosis alcohólica") + print("4. Ayuno") +def responder(self, numero): + if self.opciones[numero - 4].lower() == self.respuesta.lower(): + print("✅ Respuesta correcta.") + else: + print("❌ Respuesta incorrecta: 1, 2 y 3 son incorrectas.") + print(f"La respuesta correcta era: 4 {self.respuesta}") + # mostrat pregunta +pregunta1 = Pregunta( + "¿Cuál de los siguientes son factores predisponentes para los cálculos de colesterol?", + "Ayuno", + ["Fibrosis quística", "Hemólisis crónica", "Cirrosis alcohólica", "Ayuno"] +) +pregunta1.mostrar_pregunta() +# Responder a la pregunta +respuesta_usuario = int(input("Selecciona el número de tu respuesta: ")) +pregunta1.responder(respuesta_usuario) +elif respuesta_usuario == 1 or respuesta_usuario == 2 or respuesta_usuario == 3: + print("⚠️ Entrada inválida. Debes escribir un número válido de las opciones.") diff --git a/clase1/Lizeth_Albacura.py b/clase1/Lizeth_Albacura.py new file mode 100644 index 0000000..bb3e692 --- /dev/null +++ b/clase1/Lizeth_Albacura.py @@ -0,0 +1,45 @@ +#Clase1-ejercicios-Lizeth Albacura + +if __name__ == "__main__": + print("Saludos, soy Lizeth Albacura") + +#Ejercicio 1: números primos + +def es_primo(número): + if número < 2: + return False + for i in range(2, int(número ** 0.5)+1): + if número % i == 0: + return False + return True + +n = int(input("Ingrese el número que desee: ")) + +print(f"números primos del 1 al {n}:") +for i in range(1, n + 1): + if es_primo(i): + print(i) + +#Ejercicio 2:Menú interactivo + +import datetime +def menú(): + print("Bienvenido a este menú interactivo") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + print("¡Encomienda a Dios tu camino confía en Él, y Él actuará.Salmo 37:5!)") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print("Fecha actual:", fecha_actual.strftime("%d/%m/%Y %H:%M:%S")) + elif opcion == "3": + print("Hasta luego, que tenga un buen día") + return + else: + print("Opción no válida. Intentalo otra vez.") + +menú() diff --git "a/clase1/Valeria_Qui\303\261onez.py" "b/clase1/Valeria_Qui\303\261onez.py" new file mode 100644 index 0000000..1a9ae36 --- /dev/null +++ "b/clase1/Valeria_Qui\303\261onez.py" @@ -0,0 +1,34 @@ +# Clase 1 – Fundamentos de Python +valeria Beatriz Quiñonez Rodriguez +# Ejercicio 1: Números primos +def es_primo(n): + if n <= 2: + return False + for i in range(2, int(n**0.5) + 1): + if n % i == 0: + return False + return True +n = int(input("Ingrese un número: ")) +print (f"Números primos del 1 al n : {n}") +for i in range(1, n + 1): + if es_primo(i): + print(i, end=' ') +#Ejercicio 2: Menu interactivo +def menu(frase_motivacional): + print("Bienvenido al menú interactivo") + print("1. Frase motivacional") + print("2. Mostrar la fecha y hora actual") + print("3. Salir") +opcion = int(input("Seleccione una opción: ")) +if opcion == 1: + print("Haz tu vida un sueño, y tu sueño una realidad.") +elif opcion == 2: + print("Confia en tus esfuerzos, el éxito llegará.") +elif opcion == 3: + print("La unica manera de hacer un gran trabajo es amar lo que haces.") +opcion = int(input("Seleccione una opción: 1, 2 o 3: ")) +if opcion == 1: + print("Haz tu vida un sueño, y tu sueño una realidad.") + from datetime import datetime + fecha_hora_actual = datetime.now() + print("Fecha y hora actual: 19:53 pm ", fecha_hora_actual) diff --git a/clase1/Villavicencio_Belen.py b/clase1/Villavicencio_Belen.py new file mode 100644 index 0000000..ce17316 --- /dev/null +++ b/clase1/Villavicencio_Belen.py @@ -0,0 +1,38 @@ +def es_primo(n): + """Determina si un número es primo.""" + if n <= 1: + return False + for i in range(2, int(n**0.5) + 1): + if n % i == 0: + return False + return True + +n = int(input("Ingrese un número: ")) +print(f"Números primos del 1 al {n}:") +for i in range(1, n+1): + if es_primo(i): + print(i) + +# Ejercicio 2: Menú interactivo + +import datetime + +while True: + print("\nMenú:") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir") + + opcion = input("Selecciona una opción: ") + + if opcion == "1": + print("🚀 ¡Tú puedes con todo! Sigue luchando por tus sueños.") + elif opcion == "2": + print("📅 La fecha actual es:", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + elif opcion == "3": + print("👋 ¡Hasta pronto, te saluda Belén Villavicencio de la clase de PYTHON!") + break + else: + print("❌ Opción no válida. Intenta de nuevo.") + + \ No newline at end of file diff --git a/clase1/Wendy_Moreno.py b/clase1/Wendy_Moreno.py new file mode 100644 index 0000000..7e300c7 --- /dev/null +++ b/clase1/Wendy_Moreno.py @@ -0,0 +1,73 @@ +## 🧪 Ejercicio 1: Números primos +# Función para verificar si un número es primo +def es_primo(num): + if num < 2: + return False + for i in range(2, num): + if num % i == 0: + return False + return True + +# Solicita al usuario un número +n = int(input("Ingresa un número: ")) + +# Verifica si el número ingresado es primo +if es_primo(n): + print(f"✅ El número {n} es primo.") + + # Lista para guardar los números primos del 1 al n + primos = [] + for i in range(1, n + 1): + if es_primo(i): + primos.append(i) + + # Muestra la lista de números primos + print(f"Números primos del 1 al {n}:") + print(primos) +else: + print(f"❌ El número {n} NO es primo.") + + +## 🧪 Ejercicio 2: Menu interactivo +import random +from datetime import datetime + +# Lista con 10 frases motivacionales +frases = [ + "✨ Cree en ti y todo será posible.", + "💪 Nunca te rindas, los grandes logros toman tiempo.", + "🚀 El éxito es la suma de pequeños esfuerzos repetidos cada día.", + "🌟 Hoy es un buen día para empezar algo nuevo.", + "🔥 Si puedes soñarlo, puedes lograrlo.", + "🌱 Cada paso te acerca a tu meta.", + "💫 El límite es el cielo, y tú tienes alas.", + "🏆 El fracaso es solo una oportunidad para comenzar de nuevo con más inteligencia.", + "📈 Sigue adelante, lo mejor aún está por venir.", + "🎯 La disciplina tarde o temprano vence al talento." +] + +# Menú interactivo +while True: + print("\n📋 MENÚ INTERACTIVO:") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir") + + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + indice = random.randint(0, len(frases) - 1) + print("\n🧠 Frase motivacional:") + print(frases[indice]) + elif opcion == "2": + ahora = datetime.now() + print("\n📅 Fecha actual:") + print(ahora.strftime("%d/%m/%Y - %H:%M:%S")) + elif opcion == "3": + print("\n👋 ¡Gracias por usar el programa! ¡Hasta pronto!") + break + else: + print("❌ Opción no válida. Por favor, elige 1, 2 o 3.") + + + diff --git a/clase1/andrea_yanez.py b/clase1/andrea_yanez.py new file mode 100644 index 0000000..b205ec0 --- /dev/null +++ b/clase1/andrea_yanez.py @@ -0,0 +1,69 @@ +print("Hola, soy Andrea Yánez y estoy en la clase 1") + +"""" +Identificar si un numero es primo y mostrar todos los números primos hasta n + +""" +# === EJERCICIO 1: Mostrar numeros primos === +def es_primo(n): + if n < 2: + return False + for i in range(2, int(n ** 0.5) + 1): + if n % i == 0: + return False + return True + +def mostrar_primos_hasta_n(n): + print("Números primos del 1 al n:") + for n in range(1, n + 1): + if es_primo(n): + print(n, end=" ") + +"""" +Solicitar al usuario que ingrese un número + +""" +try: + n = int(input("Ingrese un número mayor a 1: ")) + if n < 1: + print("Por favor, ingrese un número mayor que 1") + else: + mostrar_primos_hasta_n(n) +except ValueError: + print("Entrada inválida. Debe ser un número entero") + +print("\nFin del ejercicio 1\n") + + +# === EJERCICIO 2: Mostrar menú === + +"""" +Crea un menú con al menos 3 opciones usando `if` y `elif`: + +- Mostrar una frase motivacional. +- Mostrar la fecha actual. +- Salir del programa. + +""" + + + +pass + +print("=== MENÚ PRINCIPAL ===") +print("1. Mostrar una frase motivacional") +print("2. Mostrar la fecha actual") +print("3. Salir") + +opcion = input("Seleccione una opción: ") + +if opcion == "1": + print("¡Un día a la vez!") +elif opcion == "2": + print("Hoy es...") +elif opcion == "3": + print("Salir") +else: + print("Opción no válida") + +print("\nFin del ejercicio 2\n") \ No newline at end of file diff --git a/clase1/carlos.bodero.py b/clase1/carlos.bodero.py new file mode 100644 index 0000000..ec19bc5 --- /dev/null +++ b/clase1/carlos.bodero.py @@ -0,0 +1,51 @@ +#clase 1 carlos bodero +#print("Clase 1") +from datetime import datetime + +def es_primo(numero): + if numero <= 1: + return False + if numero == 2: + return True + if numero % 2 == 0: + return False + for i in range(3, int(numero ** 0.5) + 1, 2): + if numero % i == 0: + return False + return True + +def numeros_primos_hasta(numero): + primos = [] + for i in range(2, numero + 1): + if es_primo(i): + primos.append(i) + return primos + +def menu(): + print("Bienvenido") + print("1) Frase motivacional") + print("2) Fecha actual") + print("3) salir") + opcion = input("Ingrese una opcion: ") + if opcion == "1": + print("¡Sigue adelante, cada día es una nueva oportunidad!") + elif opcion == "2": + fecha_actual = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + print(f"Fecha actual: {fecha_actual}") + else: + print("Saliendo del programa.") + + +if __name__ == "__main__": + #ejercicio 1 + elnumero = int(input("Ingrese un numero entero positivo: ")) + if elnumero < 0: + print("Por favor, ingrese un numero entero positivo.") + elif elnumero < 2: + print("Por favor, ingrese un numero mayor o igual a 2.") + else: + primos = numeros_primos_hasta(elnumero) + print(f"Numeros primos hasta {elnumero}: {primos}") + #ejercicio 2 + menu() + diff --git a/clase1/clase1.py b/clase1/clase1.py new file mode 100644 index 0000000..9a6a26f --- /dev/null +++ b/clase1/clase1.py @@ -0,0 +1,89 @@ +# --------------------------- +# Fundamentos de Python +# --------------------------- + +# Variables y tipos de datos + +# Operadores básicos +a = 10 +b = 3 +print('Suma:', a + b) +print('Resta:', a - b) +print('Multiplicación:', a * b) +print('División:', a / b) +print('División Entera:', a // b) +print('Módulo:', a % b) +print('Potencia:', a ** b) + +# --------------------------- +# Estructuras de control +# --------------------------- + +# Condicionales + +# numero = int(input("Ingresa un número: ")) +numero = 5 # Puedes cambiar este valor para probar diferentes condiciones +if numero > 0: + print("Es positivo") +elif numero < 0: + print("Es negativo") +else: + print("Es cero") + +# Comparaciones +x = 15 +y = 20 +print(x == y) # False +print(x != y) # True +print(x < y) # True + +# Booleanos +llueve = True +tengo_paraguas = False + +if llueve and tengo_paraguas: + print("Puedo salir tranquilo") +elif llueve and not tengo_paraguas: + print("Me voy a mojar") +else: + print("Día soleado") + +# --------------------------- +# Bucles +# --------------------------- + +# Bucle for +for i in range(5): + print("Número:", i) + +# Bucle while +contador = 0 +while contador < 5: + print("Contador:", contador) + contador += 1 + +# --------------------------- +# Funciones +# --------------------------- + +def saludar(nombre, apellido=""): + return f"Hola, {nombre} {apellido}!" + +print(saludar("John")) +print(saludar("John", "Doe")) + +def suma(x, y): + return x + y + +print("Suma:", suma(3, 4)) + +# --------------------------- +# Manejo de errores +# --------------------------- + +try: + resultado = 10 / 0 +except ZeroDivisionError: + print("No se puede dividir por cero") +finally: + print("Fin del bloque try-except") diff --git a/clase1/cuatin_daniel.py b/clase1/cuatin_daniel.py new file mode 100644 index 0000000..5b320d0 --- /dev/null +++ b/clase1/cuatin_daniel.py @@ -0,0 +1,63 @@ +import datetime + +def es_primo(n): + """Determina si un número es primo.""" + if n <= 1: + return False + if n == 2: # El único primo par + return True + if n % 2 == 0: # Descartar pares + return False + # Verificar divisores hasta √n (optimización) + for i in range(3, int(n**0.5) + 1, 2): + if n % i == 0: + return False + return True + +def ejercicio1(): + """Solicita un número al usuario y verifica si es primo.""" + try: + numero = int(input("Ingrese un número para verificar si es primo: ")) + if es_primo(numero): + print(f"{numero} es un número primo.") + else: + print(f"{numero} no es un número primo.") + except ValueError: + print("Por favor, ingrese un número válido.") + +def mostrar_menu(): + print("\n--- MENÚ PRINCIPAL ---") + print("1. Mostrar frase motivacional") + print("2. Mostrar fecha actual") + print("3. Salir") + +def ejercicio2(): + frases_motivacionales = [ + "¡Tú puedes lograr todo lo que te propongas! 💪", + "Cada día es una nueva oportunidad para ser mejor. 🌟", + "La perseverancia es la clave del éxito. 🚀", + "No te rindas, el éxito está más cerca de lo que piensas. 🌈", + "Cree en ti mismo y todo será posible. ✨" + ] + while True: + mostrar_menu() + opcion = input("Selecciona una opción (1-3): ") + + if opcion == "1": + import random + frase = random.choice(frases_motivacionales) # Selecciona una frase ale + print(f"\nFrase motivacional: {frase}") + elif opcion == "2": + fecha_actual = datetime.datetime.now().strftime("%d/%m/%Y") + print(f"\nLa fecha actual es: {fecha_actual}") + elif opcion == "3": + print("\n¡Hasta luego! 👋") + break + else: + print("\n❌ Opción no válida. Por favor, elige 1, 2 o 3.") + +if __name__ == "__main__": + print("Bienvenido al programa de ejercicios.") + ejercicio1() + ejercicio2() + print("Gracias por participar. ¡Hasta la próxima!") \ No newline at end of file diff --git a/clase1/edisontana.py b/clase1/edisontana.py new file mode 100644 index 0000000..460857d --- /dev/null +++ b/clase1/edisontana.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# tarea1.py +# +# Copyright 2025 edisontana +# +# Tarea 1. +# Programa que solicita al usuario un número n y visualiza todos los números primos del 1 al n. + +from datetime import datetime + +def esprimo(inumero): + """ + Funcion para saber si un numero es primo. + """ + if inumero <= 1: + False + for i in range( 2, int( inumero ** 0.5) + 1): + if inumero % i == 0: + return False + return True + +def evaluanumeros(n): + listaprimos = [] + icontador = 1 + x = 1 + while True: + if icontador <= n: + if esprimo(x): + listaprimos.append(x) + icontador = icontador + 1 + x = x + 1 + else: + break + print(f"Resultado: Los {n} numeros primos son: ") + print(listaprimos) + + +def visualizafrase(): + texto = "Los buenos equipos incorporan el trabajo en grupo \n a la cultura, creando así los pilares del éxito." + frase = f"{texto:>50}" + texto2 = "Ted Sundquist" + autor = f"{texto2:>50}" + print(frase) + print(autor) + print("") + +def visualizafechaactual(): + print(datetime.now()) + +def muestramenu(opcion): + if opcion == 1: + visualizafrase() + elif opcion == 2: + visualizafechaactual() + else: + quit() + +if __name__ == '__main__': + print("Programa para hallar 'n' numero primos") + print("Realizado por 2025 Edison TANA") + n = int(input("¿Cuantos números primos desea, por favor digite aquí? (numero): ")) + evaluanumeros(n) + print("------------------") + print("Menu interactivo") + print("1. Ver frase motivacional") + print("2. Ver hora actual") + print("3. Salir") + eleccion = int(input("Por favor digite su opcion (1-3): ")) + muestramenu(eleccion) + print("Fin del programa") + + diff --git a/clase1/edwin_rodriguez.py b/clase1/edwin_rodriguez.py new file mode 100644 index 0000000..cf3cd64 --- /dev/null +++ b/clase1/edwin_rodriguez.py @@ -0,0 +1,147 @@ +import math + +# =============================================================== +# PASO 1: Definir la función que comprueba si un número es primo +# =============================================================== +def es_primo(numero): + """ + Función auxiliar que determina si un número es primo. + Devuelve True si lo es, y False si no lo es. + """ + # Los números menores o iguales a 1 no son considerados primos. + if numero <= 1: + return False + + # El 2 es el único número primo que es par. + if numero == 2: + return True + + # Si el número es par y no es 2, no es primo. + if numero % 2 == 0: + return False + + # Revisamos solo los divisores impares hasta la raíz cuadrada del número. + # Es una optimización clave que acelera mucho el proceso. + limite = int(math.sqrt(numero)) + 1 + for divisor in range(3, limite, 2): # El '2' al final hace que salte de 2 en 2 (3, 5, 7...) + if numero % divisor == 0: + return False # Si encontramos un divisor, ya no es primo. + + # Si el bucle termina sin encontrar divisores, el número es primo. + return True + +# =============================================================== +# PASO 2: Escribir el programa principal que usa la función +# =============================================================== + +# --- Programa Principal --- + +print("--- Buscador de Números Primos --- por Edwin Rodriguez con el apoyo de IA :-)") + +# 1. Solicitar el número al usuario y validarlo +while True: + try: + n_str = input("Introduce un número entero hasta el cual buscar primos: ") + n = int(n_str) + if n >= 2: + break # El número es válido, salimos del bucle. + else: + print("Por favor, introduce un número que sea 2 o mayor.") + except ValueError: + print("Entrada no válida. Debes introducir un número entero.") + +# 2. Crear una lista para almacenar los números primos encontrados +lista_primos_encontrados = [] + +# 3. Recorrer todos los números desde 2 hasta n +print(f"\nBuscando números primos del 1 al {n}...") +for numero_a_evaluar in range(2, n + 1): + + # 4. Llamar a nuestra función para cada número + if es_primo(numero_a_evaluar): + # Si la función devuelve True, añadimos el número a la lista + lista_primos_encontrados.append(numero_a_evaluar) + +# 5. Mostrar el resultado final al usuario +print("\n¡Búsqueda completada!") +print(f"Los números primos encontrados son:") +print(lista_primos_encontrados) + + +# Importamos los módulos necesarios al principio del script. +# - 'random' para elegir una frase al azar. +# - 'datetime' para obtener la fecha actual. +# - 'locale' para mostrar la fecha en español (opcional pero recomendado). +import random +from datetime import date +import locale + +# --- Configuración Inicial (Opcional pero mejora la experiencia) --- +# Intentamos configurar el idioma a español para que la fecha se muestre correctamente. +# Si el sistema no tiene el paquete de idioma 'es_ES.UTF-8', usará el formato por defecto. +try: + # Para sistemas Linux/macOS + locale.setlocale(locale.LC_TIME, 'es_ES.UTF-8') +except locale.Error: + try: + # Para sistemas Windows + locale.setlocale(locale.LC_TIME, 'Spanish') + except locale.Error: + print("Advertencia: No se pudo configurar el idioma a español. La fecha se mostrará en el formato del sistema.") + + +# --- Lista de Frases Motivacionales --- +frases_motivacionales = [ + "El único modo de hacer un gran trabajo es amar lo que haces. - Steve Jobs", + "La vida es 10% lo que te pasa y 90% cómo reaccionas a ello. - Charles R. Swindoll", + "El éxito es la suma de pequeños esfuerzos repetidos día tras día. - Robert Collier", + "Cree que puedes y ya estás a medio camino. - Theodore Roosevelt", + "No esperes. El momento nunca será el adecuado. - Napoleon Hill" +] + + +# --- Bucle Principal del Menú --- +# Usamos un bucle 'while True' para que el menú se muestre repetidamente +# hasta que el usuario elija la opción de salir. +while True: + # 1. Mostrar las opciones del menú al usuario + print("\n" + "="*30) + print(" MENÚ PRINCIPAL USANDO ASISTENTE DE IA ") + print("="*30) + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + print("="*30) + + # 2. Solicitar la elección del usuario + opcion = input("Por favor, elige una opción (1, 2 o 3): ") + + # 3. Procesar la elección usando if/elif/else + if opcion == '1': + # Opción 1: Mostrar frase motivacional + print("\n✨ Frase del día ✨") + frase_elegida = random.choice(frases_motivacionales) + print(f"-> {frase_elegida}") + input("\n(Presiona Enter para volver al menú...)") # Pausa para que el usuario pueda leer + + elif opcion == '2': + # Opción 2: Mostrar la fecha actual + print("\n📅 Fecha Actual 📅") + fecha_de_hoy = date.today() + # Usamos .strftime() para formatear la fecha de una manera legible + # %A: Nombre completo del día de la semana (Lunes) + # %d: Día del mes (01, 31) + # %B: Nombre completo del mes (Enero) + # %Y: Año con 4 dígitos (2023) + print(f"-> Hoy es {fecha_de_hoy.strftime('%A, %d de %B de %Y')}") + input("\n(Presiona Enter para volver al menú...)") # Pausa + + elif opcion == '3': + # Opción 3: Salir del programa + print("\n¡Gracias por usar el programa! ¡Hasta luego! 👋") + break # 'break' rompe el bucle 'while True' y termina el programa + + else: + # Si el usuario introduce algo diferente a '1', '2' o '3' + print("\n❌ Opción no válida. Por favor, introduce un número del 1 al 3.") + input("\n(Presiona Enter para intentarlo de nuevo...)") \ No newline at end of file diff --git a/clase1/erika_torres.py b/clase1/erika_torres.py new file mode 100644 index 0000000..61097a8 --- /dev/null +++ b/clase1/erika_torres.py @@ -0,0 +1,53 @@ + + +## 🧪 Ejercicio 1: Números primos + +def es_primo(num): + if num < 2: + return False + for i in range(2, int(num ** 0.5) + 1): + if num % i == 0: + return False + return True + +def mostrar_primos_hasta_n(n): + print(f"Números primos del 1 al {n}:") + for i in range(1, n + 1): + if es_primo(i): + print(i, end=" ") + +# Programa principal +try: + n = int(input("Ingresa un número entero positivo: ")) + if n < 1: + print("Por favor, ingresa un número mayor o igual a 1.") + else: + mostrar_primos_hasta_n(n) +except ValueError: + print("Entrada inválida. Por favor ingresa un número entero.") + +## 🧪 Ejercicio 2: Menú interactivo + +import datetime + +def mostrar_menu(): + print("\n📋 MENÚ PRINCIPAL") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + +while True: + mostrar_menu() + opcion = input("Elige una opción (1, 2 o 3): ") + + if opcion == "1": + print("\n💬 Frase motivacional:") + print("✨ El éxito es la suma de pequeños esfuerzos repetidos día tras día.") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print(f"\n📅 Fecha actual: {fecha_actual.strftime('%d/%m/%Y - %H:%M:%S')}") + elif opcion == "3": + print("\n👋 ¡Gracias por usar el programa! Hasta pronto.") + break + else: + print("⚠️ Opción no válida. Por favor, elige 1, 2 o 3.") diff --git a/clase1/george_penafiel_clase1.py b/clase1/george_penafiel_clase1.py new file mode 100644 index 0000000..212c75d --- /dev/null +++ b/clase1/george_penafiel_clase1.py @@ -0,0 +1,42 @@ +## 🧪 Ejercicio 1: Números primos + +def es_primo(numero): + if numero < 2: + return False + for i in range(2, numero): + if numero % i == 0: + return False + return True + +n = int(input("Ejercicio 1\nIngresa un número para ver todos los primos del 1 al n: ")) + +print(f"\nNúmeros primos del 1 al {n}:") +for i in range(1, n + 1): + if es_primo(i): + print(i, end=" ") + +print("\n") + +import datetime + +## 🧪 Ejercicio 2: Menú interactivo + +while True: + print("\n----- MENÚ -----") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + + opcion = input("Elige una opción (1, 2 o 3): ") + + if opcion == "1": + print("¡Tú puedes lograrlo, no te rindas nunca!") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print("La fecha y hora actual es:", fecha_actual) + elif opcion == "3": + print("¡Hasta luego!") + break + else: + print("Opción inválida. Intenta de nuevo.") + diff --git a/clase1/gonzalo_utreras.py b/clase1/gonzalo_utreras.py new file mode 100644 index 0000000..f450dc8 --- /dev/null +++ b/clase1/gonzalo_utreras.py @@ -0,0 +1,65 @@ +def es_primo(num): + """Devuelve True si num es un número primo, False en caso contrario.""" + if num < 2: + return False + for i in range(2, int(num**0.5) + 1): + if num % i == 0: + return False + return True + +def mostrar_primos_hasta(n): + """Muestra todos los números primos desde 1 hasta n.""" + print(f"Números primos entre 1 y {n}:") + for i in range(1, n + 1): + if es_primo(i): + print(i, end=' - ') + print() # Salto de línea final + +# Programa principal +try: + n = int(input("Introduce un número entero positivo: ")) + if n < 1: + print("Por favor, introduce un número mayor o igual a 1.") + else: + mostrar_primos_hasta(n) +except ValueError: + print("Entrada inválida. Debes ingresar un número entero.") + +import datetime +import random + +# Lista de frases motivacionales +frases = [ + "🌟 Cree en ti y todo será posible.", + "🚀 Cada día es una nueva oportunidad para mejorar.", + "💪 El esfuerzo de hoy es el éxito de mañana.", + "🔥 No te detengas hasta estar orgulloso.", + "🌈 Si puedes soñarlo, puedes lograrlo.", + "🧠 La mente es poderosa. Llénala de pensamientos positivos.", + "🌱 El crecimiento comienza al salir de tu zona de confort.", + "⏳ El tiempo es ahora. ¡Aprovecha el momento!", + "🛠️ Cada error es una oportunidad para aprender.", + "🏆 La perseverancia es la clave del triunfo." +] + +def mostrar_menu(): + print("\n=== MENÚ INTERACTIVO ===") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir") + +while True: + mostrar_menu() + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + frase = random.choice(frases) + print(f"\n{frase}") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print(f"\n📅 Fecha actual: {fecha_actual.strftime('%d/%m/%Y - %H:%M:%S')}") + elif opcion == "3": + print("\n👋 ¡Hasta luego!") + break + else: + print("\n❌ Opción no válida. Intenta de nuevo.") diff --git a/clase1/jazmin_rodriguez.py b/clase1/jazmin_rodriguez.py new file mode 100644 index 0000000..635a10e --- /dev/null +++ b/clase1/jazmin_rodriguez.py @@ -0,0 +1,86 @@ + + +variable = 12 + +print("Variable:", variable) +print("tipo de variable:", type(variable)) + +_variable = "Jazmin" +print("Variable:", _variable) +print("tipo de variable:", type(_variable)) + +variable2 = True +print("Variable:", variable2) +print("tipo de variable:", type(variable2)) + +frutas = ["manzana", "banana", "naranja"] +print("Lista de frutas:", frutas) +print("tipo de variable:", type(frutas)) + +frutas.append("kiwi") +frutas.append("pera") +frutas[1] = "fresa" + +for i in range(len(frutas)): + print("Fruta en la posición", i, ":", frutas[i]) + +print("Lista de frutas actualizada:", frutas) +print("Lista de frutas actualizada:", len(frutas)) + +url = "https://www.google.com/search?sca_esv=c9fe79b891b509d9&rlz=1C1RXQR_esEC1090EC1091&sxsrf=AE3TifMdH4J85Z_s9Qlum4GCGZAXUr0aTA:1751936487775&q=google&udm=2&fbs=AIIjpHx4nJjfGojPVHhEACUHPiMQht6_BFq6vBIoFFRK7qchKBv8IM7dq8CEqHDU3BN7lblAhsJT8_A_Kaclg0ioopJQE57ZvFQVMHSTJKIqr7PDTRrW0fpHAhCDoTXrl0eYRFTG3peOHybQI8l8HdNkuZwz9XosjicNKn9Lb56HRH8vx0mIfw_X_9oTgFUwY3gg_BTiuVcEXArhl72GVbPZtlQ52lflPA&sa=X&ved=2ahUKEwjQnZeAiKyOAxVmRDABHVJ2L9kQtKgLKAF6BAgWEAE&biw=1920&bih=911&dpr=1#vhid=1ykoVglribN-pM&vssid=mosaic" +separar_url = url.split(".") +length_url = len(separar_url) +print("URL original:", url) +print("URL separada por puntos:", separar_url) +print("Cantidad de segmentos en la URL:", length_url) +print("ultima parte de la URL:", separar_url[1]) +verduras = ("zanahoria", "brócoli", "espinaca") +# verduras[1] = "lechuga" # Esto generará un error porque las tuplas son inmutables + +# verduras.append("lechuga") +# print("Tupla de verduras:", verduras) +# print("Lista de frutas actualizada:", len(verduras)) + +# print("tipo de variable:", type(verduras)) + +carro = { + "marca": "Toyota", + "modelo": "Corolla", + "año": 2020 +} + +carro["color"] = "Rojo" +carro["año"] = "2025" +print( "Diccionario de carro:", carro) +print("tipo de variable:", type(carro)) +print("Marca del carro:", carro["marca"]) + +lista = list(frutas) +print("Lista de elementos:", lista) +print("Tipo de variable:", type(lista)) +lista.append(frutas) +print("Lista de elementos actualizada:", lista) + +lista1 = ["Hola Mundo", 122, "Programación", True, 3.14, carro] +print("Lista de elementos:", lista1) +print("Tipo de variable:", type(lista1)) +lista1.append(frutas) +print("Lista de elementos actualizada:", lista) +tupla = tuple(lista1) +print("Tupla de elementos:", tupla) +print("Tipo de variable:", type(tupla)) + +# tupla.append(frutas) # Esto generará un error porque las tuplas son inmutables + +def es_primo(num): + pass + +def ejercicio1(): + es_primo() + +def ejercicio2(): + pass + +if __name__ == "__main__": + ejercicio1() + ejercicio2() \ No newline at end of file diff --git a/clase1/jorge_guato.py b/clase1/jorge_guato.py new file mode 100644 index 0000000..d501d33 --- /dev/null +++ b/clase1/jorge_guato.py @@ -0,0 +1,49 @@ +# Ejercicio 1: Números primos +def es_primo(numero): + if numero < 2: + return False + for i in range(2, int(numero**0.5) + 1): + if numero % i == 0: + return False + return True + +def ejercicio1(): + n = int(input("Ingresa un número: ")) + print(f"Números primos del 1 al {n}:") + for num in range(1, n + 1): + if es_primo(num): + print(num, end=" ") + print() + +# Ejercicio 2: Menú interactivo +def ejercicio2(): + print("\n--- MENÚ INTERACTIVO ---") + while True: + print("\n1. Mostrar frase motivacional") + print("2. Mostrar fecha actual") + print("3. Salir") + + opcion = input("Selecciona una opción: ") + + if opcion == "1": + print("¡Hoy es un gran día para lograr tus metas!") + elif opcion == "2": + from datetime import datetime + fecha = datetime.now() + print(f"Fecha actual: {fecha.strftime('%d/%m/%Y %H:%M:%S')}") + elif opcion == "3": + print("¡Hasta pronto!") + break + else: + print("Opción no válida") + +def main(): + print("EJERCICIO 1 - NÚMEROS PRIMOS") + ejercicio1() + + print("\nEJERCICIO 2 - MENÚ INTERACTIVO") + ejercicio2() + +if __name__ == "__main__": + main() + print("¡Programa terminado!") \ No newline at end of file diff --git a/clase1/jorge_luis_castellanos.py b/clase1/jorge_luis_castellanos.py new file mode 100644 index 0000000..6579a30 --- /dev/null +++ b/clase1/jorge_luis_castellanos.py @@ -0,0 +1,54 @@ +import datetime + +#Tarea Uno +#____________________________________________________________ +#Ejercicio número 1 +#Determinar si un número ingresado es primo +#____________________________________________________________ + +def numero_primo(numero): + if numero % 2 == 0: + return False + for i in range(3, int(numero ** 0.5) + 1, 2): + if numero % i == 0: + return False + return True + +def numeros_primos(numero): + primos = [] + for i in range(2, numero + 1): + if numero_primo(i): + primos.append(i) + return primos + +#____________________________________________________________ +#Ejercicio número 2 +#Menú interactivo +#____________________________________________________________ + +def menu(): + print("--- Bienvenido al menú interactivo ---") + print("|1| Frase motivacional") + print("|2| Fecha actual") + print("|3| Salir") + opcion = input("Ingrese una opcion: ") + if opcion == "1": + print("🎯 El éxito es la suma de pequeños esfuerzos repetidos día tras día.") + elif opcion == "2": + fecha_actual = print(" 🗓️ La fecha actual es: ", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + else: + print("👋🏼 Fin del programa, Hasta pronto.") + + +if __name__ == "__main__": + + #Ejercicio número 1 + numero = int(input("Ingrese un número mayor a 2: ")) + if numero <= 2: + print("Por favor, ingrese un número mayor a 2.") + else: + primos = numeros_primos(numero) + print(f"Numeros primos hasta {numero}: {primos}") + + #Ejercicio número 2 + menu() \ No newline at end of file diff --git a/clase1/marlon_rivera.py b/clase1/marlon_rivera.py new file mode 100644 index 0000000..6bde6b0 --- /dev/null +++ b/clase1/marlon_rivera.py @@ -0,0 +1,53 @@ +# ## 🧪 Ejercicio 1: Números primos + +# Crea un programa que solicite al usuario un número `n` y muestre todos los números primos del 1 al `n`. + +# ### 💡 Sugerencia: +# Usa una función `es_primo()` para verificar si un número es primo. + +def es_primo(numero): + if numero < 2: + return False + for i in range(2, int(numero**0.5) + 1): + if numero % i == 0: + return False + return True + +n = int(input("Ingrese un número entero positivo: ")) + +print(f"Números primos entre 1 y {n}:") +for num in range(1, n + 1): + if es_primo(num): + print(num, end=" ") + + +# ## 🧪 Ejercicio 2: Menú interactivo + +# Crea un menú con al menos 3 opciones usando `if` y `elif`: + +# - Mostrar una frase motivacional. +# - Mostrar la fecha actual. +# - Salir del programa. + +import datetime + +while True: + print("MENÚ") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + print("Eres capaz de TODO.") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print("Fecha y hora actual:", fecha_actual.strftime("%Y-%m-%d %H:%M:%S")) + elif opcion == "3": + print("¡Hasta pronto!") + break + else: + print("Opción inválida. Intenta de nuevo.") + + diff --git a/clase1/milton_chiluisa.py b/clase1/milton_chiluisa.py new file mode 100644 index 0000000..f69e88b --- /dev/null +++ b/clase1/milton_chiluisa.py @@ -0,0 +1,44 @@ +def es_primo(numero): + + if numero <= 1: + return False + return True + elif numero % 2 == 0: + return False + else: + + i = 3 + while i * i <= numero: + if numero % i == 0: + return False + i += 2 + return True + +def mostrar_primos_hasta_n(): + + while True: + try: + n_str = input("Por favor, ingresa un número entero positivo (n): ") + n = int(n_str) + if n <= 0: + print("Por favor, ingresa un número entero positivo mayor que cero. Inténtalo de nuevo.") + else: + break + except ValueError: + print("Entrada inválida. Por favor, ingresa solo números enteros. Inténtalo de nuevo.") + + print(f"\nNúmeros primos del 1 al {n}:") + primos_encontrados = False + for i in range(1, n + 1): + if es_primo(i): + print(i) + primos_encontrados = True + + if not primos_encontrados and n > 1: + print(f"No se encontraron números primos en el rango de 1 a {n}. (El 2 es el primer primo, si n es menor que 2)") + elif not primos_encontrados and n <= 1: + print(f"No se encontraron números primos en el rango de 1 a {n}.") + + +if __name__ == "__main__": + mostrar_primos_hasta_n() \ No newline at end of file diff --git a/clase1/pablo_colcha.py b/clase1/pablo_colcha.py new file mode 100644 index 0000000..a42ed5a --- /dev/null +++ b/clase1/pablo_colcha.py @@ -0,0 +1,59 @@ + +"""## 🧪 Ejercicio 1: Números primos + +Crea un programa que solicite al usuario un número `n` y muestre todos los números primos del 1 al `n`. + +### 💡 Sugerencia: +Usa una función `es_primo()` para verificar si un número es primo.""" + +# Función para verificar si un número es primo +def es_primo(num): + if num < 2: + print(f"{num} no es primo (menor que 2)") + return False + for i in range(2, int(num**0.5) + 1): # Solo hasta la raíz cuadrada + if num % i == 0: + print(f"{num} no es primo (divisible por {i})") + return False + return True + +# Solicitar al usuario el valor de n +n = int(input("Ingrese un número entero positivo: ")) + +print(f"Números primos entre 1 y {n}:") + +# Imprimir los números primos desde 1 hasta n +for i in range(1, n + 1): + if es_primo(i): + print(f" {i} es primo") + +"""## 🧪 Ejercicio 2: Menú interactivo + +Crea un menú con al menos 3 opciones usando `if` y `elif`: + +- Mostrar una frase motivacional. +- Mostrar la fecha actual. +- Salir del programa. """ + +import datetime + +while True: + print("\n--- MENÚ INTERACTIVO ---") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + + opcion = input("Selecciona una opción (1-3): ") + + if opcion == "1": + print("Nunca te rindas. ¡Los grandes logros requieren tiempo y esfuerzo!") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print(f" La fecha y hora actual es: {fecha_actual.strftime('%d/%m/%Y %H:%M:%S')}") + elif opcion == "3": + print(" ¡Hasta luego!") + break + else: + print("Opción no válida. Intenta de nuevo.") + +print("Fin del programa.") diff --git a/clase1/readme.md b/clase1/readme.md new file mode 100644 index 0000000..938f0cc --- /dev/null +++ b/clase1/readme.md @@ -0,0 +1,34 @@ +# Clase 1 – Fundamentos de Python + +## 🎯 Objetivo: +Aplicar estructuras básicas de programación en Python: variables, condicionales, bucles y funciones. + +--- + +## 📋 Instrucciones: + +1. Realiza un *fork* del repositorio principal del curso a tu cuenta personal de GitHub. +2. Clona tu fork. +3. Crea un archivo con tu nombre: nombre_apellido.py. +4. Resuelve los ejercicios de abajo. +5. Haz commit, push y un Pull Request con el título:\ + *"Clase 1 - TuNombre TuApellido"* + +--- + +## 🧪 Ejercicio 1: Números primos + +Crea un programa que solicite al usuario un número n y muestre todos los números primos del 1 al n. + +### 💡 Sugerencia: +Usa una función es_primo() para verificar si un número es primo. + +--- + +## 🧪 Ejercicio 2: Menú interactivo + +Crea un menú con al menos 3 opciones usando if y elif: + +- Mostrar una frase motivacional. +- Mostrar la fecha actual. +- Salir del programa. \ No newline at end of file diff --git a/clase1/ronald_diaz.py b/clase1/ronald_diaz.py new file mode 100644 index 0000000..efdf437 --- /dev/null +++ b/clase1/ronald_diaz.py @@ -0,0 +1,60 @@ +""" +Ejercio 1 +Numeros primos + +Ejercicio 2 +Menu +""" +from datetime import datetime + +def es_primo(num): + bandera = 0 + for contador in range(1, num+1): + if num % contador==0: + bandera +=1 + if bandera <= 2: + print(num) + +def ejercicio1(): + try: + while True: + numero = int(input("Ingrese un número entero positivo:")) + if numero > 0: + break + for cont in range(1, numero+1): + es_primo(cont) + except: + print("Debe ingresar un número entero") + + +def menu(): + while True: + print("*********************************************************") + print("Seleccione una opción del menú (ingrese el número)") + print("*********************************************************") + print("1: Frase Motivacional") + print("2: Fecha Actual") + print("3: Salir") + print("*********************************************************") + try: + opcion= int(input("Opción: ")) + if opcion == 1: + print("Cree que puedes, y ya estarás a mitad de camino") + elif opcion == 2: + print(f"Fecha: {datetime.now().year} - {datetime.now().month} - {datetime.now().day} ") + elif opcion == 3: + break + else: + print("Debe seleccionar una de las opciones del menu") + + except: + print("Debe ingresar un numero") + +def ejercicio2(): + menu() + +if __name__ == "__main__": + ejercicio1() + ejercicio2() + + diff --git a/clase1/santiago_calvopina.py b/clase1/santiago_calvopina.py new file mode 100644 index 0000000..6be382d --- /dev/null +++ b/clase1/santiago_calvopina.py @@ -0,0 +1,46 @@ +from datetime import datetime + +def verificar_primo(num): + if num <= 1: + return False + for divisor in range(2, num): + if num % divisor == 0: + return False + return True + +def listar_primos(limite): + return [numero for numero in range(2, limite + 1) if verificar_primo(numero)] + +def mostrar_menu(): + while True: + print("\n=== MENÚ PRINCIPAL ===") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Salir del programa") + + opcion = input("Selecciona una opción (1-3): ") + + if opcion == '1': + print("La vida es un viaje, no un destino..") + elif opcion == '2': + ahora = datetime.now() + print("La Fecha y hora actual es:", ahora.strftime("%d/%m/%Y %H:%M:%S")) + elif opcion == '3': + print("¡CHAIIITOO!") + break + else: + print("La Opción no es válida. Ingresa una opción valida.") + +if __name__ == "__main__": + print("Iniciando ...") + try: + numero_usuario = int(input("Ingresa un número positivo mayor que 1: ")) + if numero_usuario > 1: + lista_primos = listar_primos(numero_usuario) + print(f"Los números primos hasta {numero_usuario} son: {lista_primos}") + else: + print("El número debe ser mayor que 1.") + except ValueError: + print("Debe ingresar un número entero válido.") + + mostrar_menu() \ No newline at end of file diff --git a/clase1/valeria_ramos.py b/clase1/valeria_ramos.py new file mode 100644 index 0000000..8c6d240 --- /dev/null +++ b/clase1/valeria_ramos.py @@ -0,0 +1,35 @@ +#numeros primos ejercicio 1 + +from datetime import date + +def es_primo(number): + if number <= 1: + return False + for i in range (2,number): + if number % i == 0: + return False + return True + + +number = int(input("Ingresa un número: ")) +if es_primo(number): + print(f"{number} ES UN NÚMERO PRIMO.") +else: + print(f"{number} NO ES UN NÚMERO PRIMO.") + + +#Menu ejercicio 2 +option1 = 1 +option2 = 2 +option3 = 3 +resultOption = int(input(f"Escribe el número de la opción que necesites: Frase: {option1}, Fecha: {option2}, Salir:{option3} ")) +if resultOption == 1: + print ("Invertir tiempo en aprender a programar es invertir en mi futuro.") +elif resultOption == 2: + dateActual = date.today() + print(f"La fecha de hoy es:{dateActual}") +elif resultOption == 3: + print ("XSaliendo, Saludos..") + exit() +else: + print ("El número ingresado no es correcto. Selecciona una opción valida") \ No newline at end of file diff --git a/clase1/walter_nunez.py b/clase1/walter_nunez.py new file mode 100644 index 0000000..fda22f1 --- /dev/null +++ b/clase1/walter_nunez.py @@ -0,0 +1,61 @@ +import datetime + +def es_primo(numero): + if numero < 2: + return False + for i in range(2, int(numero**0.5) + 1): + if numero % i == 0: + return False + return True + +def ejercicio_1(): + try: + n = int(input("Ingrese un número: ")) + print(f"Números primos del 1 al {n}:") + for i in range(1, n + 1): + if es_primo(i): + print(i, end=" ") + print("\n") # Salto de línea final + except ValueError: + print("Por favor, ingrese un número válido.\n") + +def ejercicio_2(): + while True: + print("\n--- MENÚ EJERCICIO 2 ---") + print("1. Mostrar una frase motivacional") + print("2. Mostrar la fecha actual") + print("3. Volver al menú principal") + + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + print(" ¡Sigue adelante, lo mejor está por venir!") + elif opcion == "2": + fecha_actual = datetime.datetime.now() + print("Fecha actual:", fecha_actual.strftime("%Y-%m-%d %H:%M:%S")) + elif opcion == "3": + break + else: + print(" Opción no válida. Intenta de nuevo.") + +def menu_principal(): + while True: + print("\n=== MENÚ PRINCIPAL ===") + print("1. Ejecutar Ejercicio 1: Números primos") + print("2. Ejecutar Ejercicio 2: Menú interactivo") + print("3. Salir") + + opcion = input("Selecciona una opción (1-3): ") + + if opcion == "1": + ejercicio_1() + elif opcion == "2": + ejercicio_2() + elif opcion == "3": + print(" ¡Programa finalizado!") + break + else: + print("Opción no válida. Intenta de nuevo.") + +if __name__ == "__main__": + menu_principal() diff --git a/clase1/xavier_arellano.py b/clase1/xavier_arellano.py new file mode 100644 index 0000000..4116ea5 --- /dev/null +++ b/clase1/xavier_arellano.py @@ -0,0 +1,58 @@ +<<<<<<< HEAD +from datetime import datetime + +def es_primo(num): + for n in range(2, num): + if num % n == 0: + print("El número", num, "no es primo:", n, "es divisor") + return False + print("El número", num, "es primo") + return True + +def menu(num2): + if num2 == 1: + print("La frase motivacional es: '¡Sigue adelante, nunca te rindas!'") + elif num2 == 2: + print("La fecha de hoy es:", datetime.now().strftime("%d/%m/%Y")) + elif num2 == 3: + print("La hora actual es:", datetime.now().strftime("%H:%M:%S")) + else: + print("¡Gracias por usar el programa!") + +if __name__ == "__main__": + num1 = int(input("Ingrese el primer número: ")) + num2 = int(input("Ingrese el segundo número: ")) + es_primo(num1) + es_primo(num2) + + num3 = int(input("Ingrese un número para el menú (1-4): ")) +======= +from datetime import datetime + +def es_primo(num): + for n in range(2, num): + if num % n == 0: + print("El número", num, "no es primo:", n, "es divisor") + return False + print("El número", num, "es primo") + return True + +def menu(num2): + if num2 == 1: + print("La frase motivacional es: '¡Sigue adelante, nunca te rindas!'") + elif num2 == 2: + print("La fecha de hoy es:", datetime.now().strftime("%d/%m/%Y")) + elif num2 == 3: + print("La hora actual es:", datetime.now().strftime("%H:%M:%S")) + else: + print("¡Gracias por usar el programa!") + +if __name__ == "__main__": + num1 = int(input("Ingrese el primer número: ")) + num2 = int(input("Ingrese el segundo número: ")) + es_primo(num1) + es_primo(num2) + + num3 = int(input("Ingrese un número para el menú (1-4): ")) +>>>>>>> 3d963b71f3488bde9135583b06a8c96b20a825b6 + menu(num3) \ No newline at end of file diff --git a/clase2/Lizeth_ Albacura.py b/clase2/Lizeth_ Albacura.py new file mode 100644 index 0000000..d250419 --- /dev/null +++ b/clase2/Lizeth_ Albacura.py @@ -0,0 +1,155 @@ +#CLASE2-Lizeth Albacura + +#EJERCICIO 1: Objetos + +#Este objeto representa una plancha alisadora de cabello. +# Tiene propiedades como marca, modelo, color y temperatura máxima. +#Puede encenderse, ajustar la temperatura, y apagarse. +# Elegí este objeto porque es útil y común, especialmente en rutinas personales. + +""" +Plancha de Cabello: +- Marca +- Modelo +- Color +- Temperatura máxima + +Métodos: +- encender() +- ajustar_temperatura() +- apagar() +""" + +class PlanchaCabello: + def __init__(self, marca, modelo, color, temp_max): + self.marca = marca + self.modelo = modelo + self.color = color + self.temp_max = temp_max + self.encendida = False + self.temperatura_actual = 0 + + def encender(self): + self.encendida = True + self.temperatura_actual = 180 # temperatura inicial + print(f"La plancha {self.marca} está encendida a {self.temperatura_actual}°C.") + + def ajustar_temperatura(self, nueva_temp): + if self.encendida: + if nueva_temp <= self.temp_max: + self.temperatura_actual = nueva_temp + print(f"Temperatura ajustada a {nueva_temp}°C.") + else: + print(f"La temperatura máxima es {self.temp_max}°C.") + + def apagar(self): + self.encendida = False + self.temperatura_actual = 0 + print(f"La plancha {self.marca} está apagada.") + + +mi_plancha = PlanchaCabello("Revlon", "NV9193", "Lila", 200) + + +mi_plancha.encender() +mi_plancha.ajustar_temperatura(200) +mi_plancha.apagar() + + +print("Marca:", mi_plancha.marca) +print("Modelo:", mi_plancha.modelo) +print("Color:", mi_plancha.color) +print("Temperatura máxima:", mi_plancha.temp_max, "°C") + +#EJERCICIO 2: Listas y diccionarios + +#Películas favoritas + +peliculas_favoritas = ["El diario de Bridget Jones", "Legalmente rubia", "La Momia", "V de venganza"] + +#Diccionario con información de cada película +info_peliculas = { + "El diario de Bridget Jones": { + "Género": "Comedia romántica", + "Año": 2001 + }, + "Legalmente rubia": { + "Género": "Comedia", + "Año": 2001 + }, + "La Momia": { + "Género": "Acción / Aventura", + "Año": 1999 + }, + "V de venganza": { + "Género": "Ciencia ficción", + "Año": 2005 + } +} + +#Imprimir las operaciones +print("\nMis películas favoritas son:\n") +for pelicula in peliculas_favoritas: + print("-", pelicula) + +print("\nDetalles de las películas:\n") +for nombre in peliculas_favoritas: + datos = info_peliculas[nombre] + print(f"{nombre}:\nGénero:{datos['Género']}, \nAño: {datos['Año']}\n") + +#EJERCICIO 3-Trivia con POO + +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def mostrar(self): + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar_respuesta(self, seleccion_usuario): + try: + indice = int(seleccion_usuario) - 1 + if self.opciones[indice].lower() == self.respuesta_correcta.lower(): + print("✅ ¡Respuesta correcta!") + else: + print(f"❌ Respuesta incorrecta. La correcta es: {self.respuesta_correcta}") + except (IndexError, ValueError): + print("Opción inválida. Intenta con otro número") + +# Preguntas disponibles +preguntas = { + 1: Pregunta( + "¿Cuál es el nevado más grande del Ecuador?", + ["Cotopaxi", "Chimborazo", "Cayambe", "Antisana"], + "Chimborazo" + ), + 2: Pregunta( + "¿Cuál es la capital de Napo?", + ["Quito", "Ambato", "Nueva Loja", "Tena"], + "Tena" + ), + 3: Pregunta( + "¿En qué provincia se encuentra el Parque Nacional Cajas?", + ["Azuay", "Loja", "El Oro", "Pichincha"], + "Azuay" + ) +} + +# Opciones +print("\nPreguntas disponibles:") +for num in preguntas: + print(f"{num}. {preguntas[num].enunciado}") + +# Selección del usuario +numero = int(input("\nIngrese el número de la pregunta (1-3): ")) + +if numero in preguntas: + preguntas[numero].mostrar() + respuesta = input("Tu respuesta (número): ") + preguntas[numero].verificar_respuesta(respuesta) +else: + print("Número de pregunta no válido") diff --git "a/clase2/Valeria_Qui\303\261onez.py" "b/clase2/Valeria_Qui\303\261onez.py" new file mode 100644 index 0000000..63cc0d9 --- /dev/null +++ "b/clase2/Valeria_Qui\303\261onez.py" @@ -0,0 +1,78 @@ +# clase 2-Estructuras y POO +Valeria Beatriz Quiñonez Rodriguez +# Ejercicio 1: Objetos +# Definimos la clase Laptop +class Laptop: + def __init__(self, marca, modelo, año, color, almacenamiento, memoria_ram=8): + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + self.almacenamiento = almacenamiento + self.memoria_ram = memoria_ram + self.estado = "apagado" + + def encender(self): + self.estado = "encendido" + print(f"La laptop {self.marca} {self.modelo} está {self.estado}.") + + def apagar(self): + self.estado = "apagado" + print(f"La laptop {self.marca} {self.modelo} está {self.estado}.") + def reiniciar(self): + if self.estado == "encendido": + print(f"La laptop {self.marca} {self.modelo} se está reiniciando.") + else: + print(f"No se puede reiniciar la laptop {self.marca} {self.modelo} porque está apagada.") +#Ejercicio 2: Listas y Diccionarios +#Lista con tus 3 peliculas favoritas +peliculas_favoritas = ["Legalmente Rubia", "Rasputia", "Shrek"] +#Imprimir lista +print("Mis películas favoritas son:") +for pelicula in peliculas_favoritas: + print(f"- {pelicula}") + #Diccionario con mis datos + mi_info = { + "nombre": "Valeria ", + "edad": 17, + "genero": "Femenino" + } + #Imprimir diccionario +print("\nMis datos:") +for clave, valor in mi_info.items(): + print(f"{clave.capitalize()}: {valor}") +#Ejercicio 3: Trivia con POO +class Pregunta: + def __init__(self, pregunta, respuesta_correcta, respuestas_incorrectas): + self.pregunta = pregunta + self.respuesta_correcta = respuesta_correcta + self.respuestas_incorrectas = respuestas_incorrectas + def mostrar_pregunta(self): + print(f"Pregunta: {self.pregunta}") + print("Respuestas posibles:") + for i, respuesta in enumerate(self.respuestas_incorrectas, start=1): + print(f"{i}. {respuesta}") + print(f"Respuesta correcta: {self.respuesta_correcta}") + print("¿Cuál de los siguientes son factores predisponentes para los cálculos de colesterol?:") + print("1. Fibrosis quística") + print("2. Hemólisis crónica") + print("3. Cirrosis alcohólica") + print("4. Ayuno") +def responder(self, numero): + if self.opciones[numero - 4].lower() == self.respuesta.lower(): + print("✅ Respuesta correcta.") + else: + print("❌ Respuesta incorrecta: 1, 2 y 3 son incorrectas.") + print(f"La respuesta correcta era: 4 {self.respuesta}") + # mostrat pregunta +pregunta1 = Pregunta( + "¿Cuál de los siguientes son factores predisponentes para los cálculos de colesterol?", + "Ayuno", + ["Fibrosis quística", "Hemólisis crónica", "Cirrosis alcohólica", "Ayuno"] +) +pregunta1.mostrar_pregunta() +# Responder a la pregunta +respuesta_usuario = int(input("Selecciona el número de tu respuesta: ")) +pregunta1.responder(respuesta_usuario) +elif respuesta_usuario == 1 or respuesta_usuario == 2 or respuesta_usuario == 3: + print("⚠️ Entrada inválida. Debes escribir un número válido de las opciones.") diff --git a/clase2/Villavicencio_Belen.py b/clase2/Villavicencio_Belen.py new file mode 100644 index 0000000..493e2e2 --- /dev/null +++ b/clase2/Villavicencio_Belen.py @@ -0,0 +1,85 @@ +# Clase que representa un celular +class Celular: + def __init__(self, marca, modelo, año, color): + """Constructor del objeto celular.""" + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + + def llamar(self, numero): + """Simula una llamada a un número.""" + print(f"Llamando al {numero} desde un {self.marca} {self.modelo}...") + + def enviar_mensaje(self, numero, mensaje): + """Simula el envío de un mensaje a un número.""" + print(f"Enviando mensaje a {numero}: {mensaje}") + + +# Crear una instancia (objeto) de la clase Celular +mi_celular = Celular("Apple", "iPhone 13", 2021, "Negro") + +# Operaciones con el objeto +mi_celular.llamar("0987654321") +mi_celular.enviar_mensaje("0987654321", "Hola, ¿cómo estás?") + +""" +Este objeto representa un celular. Lo elegí porque es un dispositivo con el que interactuamos a diario. +Tiene atributos como marca, modelo, año y color, y puede realizar acciones como llamar y enviar mensajes. +Esto muestra cómo en POO los objetos agrupan datos y funciones relacionados. +""" + +# EJERCICIO 2 Explicación del objeto + +peliculas_favoritas = ["Interestelar", "El Origen", "Matrix"] + +mis_datos = { + "nombre": "Belén", + "genero": "Femenino", + "año": 2025 +} + +print("🎬 Mis películas favoritas son:", peliculas_favoritas) + +for peli in peliculas_favoritas: + print("👉", peli) + +print("📄 Mis datos personales son:", mis_datos) + +print("👤 Nombre:", mis_datos["nombre"]) +print("♀️ Género:", mis_datos["genero"]) +print("📅 Año:", mis_datos["año"]) + +# EJERCICIO 3 Clase que representa una pregunta de trivia +class Pregunta: + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar(self): + print("\n🧠 Pregunta:") + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar_respuesta(self, eleccion_usuario): + if self.opciones[eleccion_usuario - 1].lower() == self.respuesta.lower(): + print("✅ ¡Respuesta correcta!") + else: + print("❌ Respuesta incorrecta. La correcta era:", self.respuesta) + + +# Crear una instancia de la clase Pregunta +pregunta1 = Pregunta( + "¿Cuál es el lenguaje de programación que estás aprendiendo?", + ["Java", "Python", "C++", "JavaScript"], + "Python" +) + +# Mostrar la pregunta y pedir respuesta al usuario +pregunta1.mostrar() +eleccion = int(input("Elige una opción (1-4): ")) + +# Verificar la respuesta del usuario +pregunta1.verificar_respuesta(eleccion) diff --git a/clase2/Wendy_Moreno.py b/clase2/Wendy_Moreno.py new file mode 100644 index 0000000..49740f7 --- /dev/null +++ b/clase2/Wendy_Moreno.py @@ -0,0 +1,125 @@ +## 🧪 Ejercicio 1: Objetos + +#Este objeto se llama ClienteContable. Representa a un cliente que tiene un negocio y puede necesitar declarar impuestos. + +class ClienteContable: + def __init__(self, nombre, tipo_negocio, necesita_declarar): + self.nombre = nombre + self.tipo_negocio = tipo_negocio + self.necesita_declarar = necesita_declarar + + def mostrar_info(self): + print(f"📌 Cliente: {self.nombre}") + print(f"🏪 Tipo de negocio: {self.tipo_negocio}") + print(f"🧾 ¿Debe declarar impuestos?: {'Sí' if self.necesita_declarar else 'No'}") + + def declarar_impuestos(self): + if self.necesita_declarar: + print(f"✅ Declarando impuestos para {self.nombre}...") + self.necesita_declarar = False + else: + print(f"❌ {self.nombre} ya está al día con sus impuestos.") + +# Crear un objeto cliente +cliente1 = ClienteContable("Cristina Moya", "Tienda Cris", True) + +# Usar los métodos del objeto +cliente1.mostrar_info() +cliente1.declarar_impuestos() +cliente1.mostrar_info() + +## 🧪 Ejercicio 2: Listas y diccionarios +# Lista de películas favoritas +peliculas = ["Coco", "Titanic", "Rapidos y Furiosos"] + +# Diccionario con info de las películas +info_peliculas = { + "Coco": {"genero": "Animación", "año": 2017}, + "Titanic": {"genero": "Romance", "año": 1997}, + "Rapidos y Furiosos": {"genero": "Acción", "año": 2001} +} + +# Mostrar menú +print("🎬 MIS PELÍCULAS FAVORITAS") +print("1. Agregar una nueva película") +print("2. Buscar posición de una película") +print("3. Reemplazar una película por otra") + +# Opción del usuario +opcion = input("Elige una opción (1-3): ") + +if opcion == "1": + nueva = input("Escribe el nombre de la nueva película: ") + peliculas.append(nueva) + print("Película agregada correctamente.") + print("Lista actual:", peliculas) + +elif opcion == "2": + buscar = input("Escribe el nombre de la película que quieres buscar: ") + if buscar in peliculas: + posicion = peliculas.index(buscar) + print(f"La película '{buscar}' está en la posición {posicion}.") + else: + print("La película no está en la lista.") + +elif opcion == "3": + antigua = input("¿Qué película quieres reemplazar?: ") + if antigua in peliculas: + nueva = input("¿Por cuál la quieres reemplazar?: ") + index = peliculas.index(antigua) + peliculas[index] = nueva + print("Película reemplazada correctamente.") + print("Lista actual:", peliculas) + else: + print("La película que quieres reemplazar no está en la lista.") + +else: + print("Opción no válida.") + +## 🧪 Ejercicio 3: Trivia con POO + +# Clase Pregunta +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def mostrar(self): + print("\n❓", self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar(self, respuesta_usuario): + if self.opciones[respuesta_usuario - 1] == self.respuesta_correcta: + print("✅ ¡Correcto!") + return 1 + else: + print(f"❌ Incorrecto. La respuesta correcta era: {self.respuesta_correcta}") + return 0 + +# Lista de preguntas +pregunta1 = Pregunta("¿Cuál es la capital de Ecuador?", ["Guayaquil", "Quito", "Cuenca"], "Quito") +pregunta2 = Pregunta("¿Cuánto es 5 + 3?", ["6", "8", "10"], "8") +pregunta3 = Pregunta("¿Qué color resulta de mezclar azul y amarillo?", ["Verde", "Rojo", "Naranja"], "Verde") + +preguntas = [pregunta1, pregunta2, pregunta3] + +# Variable para llevar el puntaje +puntaje = 0 + +# Juego de trivia +print("BIENVENIDO A LA TRIVIA") +for pregunta in preguntas: + pregunta.mostrar() + try: + respuesta = int(input("Tu respuesta (1-3): ")) + if 1 <= respuesta <= 3: + puntaje += pregunta.verificar(respuesta) + else: + print("⚠️ Respuesta no válida. Debe ser 1, 2 o 3.") + except: + print("⚠️ Entrada inválida. Debe ser un número.") + +# Resultado final +print(f"\n🏁 Fin del juego. Tu puntaje final es: {puntaje} de {len(preguntas)}") diff --git a/clase2/carlos_bodero.py b/clase2/carlos_bodero.py new file mode 100644 index 0000000..734a491 --- /dev/null +++ b/clase2/carlos_bodero.py @@ -0,0 +1,128 @@ +#Clase 2 ejercios ,2 y 3 +#Ejercicio 1 +""" Celular: +Propiedades: + Marca --> define la marca o fabricante del dispositivo + Modelo --> el modelo del dispositivo + Año --> el año de fabricación + Color --> el color del dispositivo +Metodos: + Llamar --> realiza una llamada + Enviar mensaje --> enviar mensaje de texto a un número de teléfono + Tomar_foto --> toma una fotografía + Escuchar_Musica --> abre la aplicación para escuchar música + Ver_Video --> abre la aplicación para ver un video +""" + +class Celular: + def __init__(self): + self.marca = "" + self.modelo = "" + self.anio = "" + self.color = "" + + def __init__(self,marca,modelo,anio,color): + self.marca = marca + self.modelo = modelo + self.anio = anio + self.color = color + + def mostrarInfo(self): + print(f"Marca: {self.marca} Modelo: {self.modelo} Año: {self.anio} Color: {self.color}") + + def llamar(self,numero): + print(f"Lamando {numero}....") + + def enviarMensaje(self,numero,mensaje): + print(f"Enviado el mensaje :{mensaje}\nDestino: {numero}") + + def tomarFoto(self): + print(f"El celular {self.modelo} está tomando foto") + + def escucharMusica(self): + print(f"El celular {self.modelo} está utilizando una app para reproducir música ") + + def verVideo(self): + print(f"El celular {self.modelo} esta mostrando video desde una app") + +# clase para ejercicio 3 trivia con POO +class Pregunta: + opciones = [] + def __init__(self,pregunta,respuesta,opciones): + self.pregunta = pregunta + self.opciones = list(opciones) + self.respuesta = respuesta + + def mostrarPregunta(self): + print(f" {self.pregunta} : ") + indice = 1 + for opcion in self.opciones: + print(f" {indice} {opcion}") + indice += 1 + + def validarRespuesta(self,respuestaUsuario): + if self.respuesta == respuestaUsuario: + return True + else: + return False + + + + + + + +if __name__ == "__main__": + print("Ejercicio 1: Probando objeto...") + eltelefono = Celular("Samsung","A11","2023","blanco") + eltelefono.mostrarInfo() + eltelefono.color = "Azul" + eltelefono.mostrarInfo() + eltelefono.llamar("0983334678") + eltelefono.enviarMensaje("mensaje de prueba","0999243659") + eltelefono.escucharMusica() + eltelefono.tomarFoto() + eltelefono.verVideo() + print("-"*50) + + print("Ejercicio 2 Listas y Diccionarios") + + infoPelicula1 = {"Nombre":"Amelie","genero":"drama","Anio":2000} + infoPelicula2 = {"Nombre":"Caída del Halcón Negro","genero":"bélico","Anio":2001} + infoPelicula3 = {"Nombre":"Batman","genero":"accion","Anio":2020} + + Listado = [infoPelicula1,infoPelicula2,infoPelicula3] + + for pelicula in Listado: + print(pelicula) + + infoPelicula3["genero"]="super heroes" + infoPelicula3["Anio"] = 2021 + + infoPelicula4 = {"Nombre":"El origen","genero":"accion","Anio":2011} + + Listado.append(infoPelicula4) + Listado.remove(infoPelicula1) + + print("Después de realizar operaciones") + + for pelicula in Listado: + print(pelicula) + + print("-"*50) + print("Ejercicio 3 Trivia con POO") + pregunta1 = Pregunta("Cuál es la capital de Ecuador",3,["Ambato","Cuenca","Quito","Manta"]) + + pregunta1.mostrarPregunta() + + respuestaU = int(input("Su respuesta es (ingrese el número correspondiente):")) + + if pregunta1.validarRespuesta(respuestaU): + print("Respuesta correcta") + else: + print("Respuesta Incorrecta") + + + + + diff --git a/clase2/clase2.py b/clase2/clase2.py new file mode 100644 index 0000000..55542d3 --- /dev/null +++ b/clase2/clase2.py @@ -0,0 +1,87 @@ +# Definición de una clase +class Persona: + def __init__(self, nombre, edad): + self.nombre = nombre + self.edad = edad + + def saludar(self): + print(f"Hola, soy {self.nombre} y tengo {self.edad} años.") + +# Crear objetos +persona1 = Persona("Jazmin", 28) +persona1.saludar() + +# Atributos públicos +print(persona1.nombre) + +# --------------------------- +# Encapsulamiento +# --------------------------- + +class CuentaBancaria: + def __init__(self, titular, saldo): + self.titular = titular + self.__saldo = saldo # atributo privado + + def ver_saldo(self): + return self.__saldo + + def depositar(self, monto): + if monto > 0: + self.__saldo += monto + +cuenta = CuentaBancaria("Iván", 100) +cuenta.depositar(50) +print("Saldo actual:", cuenta.ver_saldo()) + +# --------------------------- +# Herencia +# --------------------------- + +class Animal: + def __init__(self, nombre): + self.nombre = nombre + + def hablar(self): + print("Hace un sonido") + +class Perro(Animal): + def hablar(self): + print("Guau!") + +class Gato(Animal): + def hablar(self): + print("Miau!") + +perro = Perro("Firulais") +gato = Gato("Michi") + +perro.hablar() # Guau! +gato.hablar() # Miau! + +# --------------------------- +# Polimorfismo +# --------------------------- + +def hacer_hablar(animal): + animal.hablar() + +hacer_hablar(perro) +hacer_hablar(gato) + +# --------------------------- +# isinstance y super() +# --------------------------- + +print(isinstance(perro, Animal)) + +class Estudiante(Persona): + def __init__(self, nombre, edad, carrera): + super().__init__(nombre, edad) + self.carrera = carrera + + def saludar(self): + print(f"Soy {self.nombre}, estudiante de {self.carrera}") + +estudiante1 = Estudiante("Luis", 22, "Ingeniería") +estudiante1.saludar() \ No newline at end of file diff --git a/clase2/clase2/clase2/andrea_yanez.py b/clase2/clase2/clase2/andrea_yanez.py new file mode 100644 index 0000000..a91487d --- /dev/null +++ b/clase2/clase2/clase2/andrea_yanez.py @@ -0,0 +1,188 @@ +""" +Explicar que es el objeto que hace y el proque de la elección: + - Eleji el objeto de "Servicios de Diseño" poruqe es el servicio que ofrezco como diseñadora y que me permite demostrar el uso de clases y objetos en Python. +""" + + +""" +EJERCICIO 1: Objetos + +""" + +""" +Funcion para promocionar un servicio + +""" + +class SevicioDiseno: + def __init__ (self, disenador, estudios, habilidades): + self.disenador = disenador + self.estudios = estudios + self.habilidades = habilidades + + def mostrar_informacion(self): + print(f" 📣 Diseñador: {self.disenador}") + print(f"Estudios: {self.estudios}") + print(f"Habilidades: {', '.join(self.habilidades)}\n") + +""" +Funcion para promocionar un servicio + +""" +def promocionar_servicio(servicio): + print(f"📢 Promocionando a: {servicio.disenador} con habilidades en : {', '.join(servicio.habilidades)}") + print(f"APROVECHA EL 15 % DE DESCUENTO EN TODOS LOS SERVICIOS DE DISEÑO\n"), + + +""" +Lista de Servicios de Diseño + +""" +servicios = [ + SevicioDiseno( + "Andrea Yanez", + "Universidad Tecnica de Cotopaxi", + ["Photoshop, Illustrator, Affter Effects"] + ), + SevicioDiseno( + "Carlos Lopez", + "Universidad Tecnica de Ambato", + ["Figma, Canva, Indesign"] + ) +] + +""" +Informacion de Servicios de Diseño + +""" +print("Servicios de Diseño Disponibles:\n") +for servicio in servicios: + servicio.mostrar_informacion(), + +""" +Promociones Actuales + +""" + +print("Promociones actuales:\n") +for servicio in servicios: + promocionar_servicio(servicio) + + +""" +EJERCICIO 2: Listas y diccionarios + +""" + +""" +Diccionario de peliculas favoritas + +""" +fav_peliculas = { + "Olvida de mi":{ + "genero": "Drama", + "año" : 2004 + }, + "El origen":{ + "genero": "Romance", + "año": 2009 + }, + "El numero 13":{ + "genero": "Misterio", + "año": 2006 + } +} + + +""" +Lista de peliculas favoritas + +""" +pelis_favoritas = list(fav_peliculas.keys()) + +print("\nMis 3 películas favoritas son:") +for peli in pelis_favoritas: + print(f"- {peli}") + + +""" +Informacion peliculas favoritas + +""" +print("\nMis películas favoritas:") +for peli in pelis_favoritas: + genero = fav_peliculas[peli]["genero"] + año = fav_peliculas[peli]["año"] + print(f"- {peli} - Género: {genero}, Año: {año}") + +""" +Operaciones con el diccionario de peliculas favoritas + +""" +print("\n - Generos de mis peliculas favoritas:") +for peli in pelis_favoritas: + print(f"{peli} : {fav_peliculas[peli]['genero']}") + +print("\n - Años de mis peliculas favoritas:") +for peli in pelis_favoritas: + print(f"{peli} : {fav_peliculas[peli]['año']}") + +""" +Operaciones con el diccionario de peliculas favoritas + +""" +print("\n - Peliculas del año 2006:") +for peli in fav_peliculas: + if fav_peliculas [peli]["año"] == 2006: + print(f"- {peli} ({fav_peliculas[peli]['año']})") + +""" +EJERCICIO 2: Trivia con POO + +""" +""" +Crear clase de pregunta + +""" +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + + def mostrar(self): + print(f"\n{self.enunciado}") + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar_respuesta(self, seleccion_usuario): + if self.opciones[seleccion_usuario - 1].lower () == self.respuesta_correcta.lower(): + print ("Respuesta Correcta") + else: + print(f"Incorrecto, La respuesta correcta es: {self.enunciado}") + +""" +Crear la pregunta + +""" +pregunta1 = Pregunta( + "¿Cuál es el servicio de diseño que se centra en identidad de marca?", + ["diseño publicitario","Branding","Diseño editorial","Diseño Web"], + "Branding" +) + +""" +Responder pregunta + +""" +pregunta1.mostrar() + +try: + numero = int(input("Ingrese una de las opciones (1-4): ")) + if 1 <= numero <= len(pregunta1.opciones): + pregunta1.verificar_respuesta(numero) + else: + print("Opcion Incorrecta") +except ValueError: + print("Ingresa una opncion del 1 al 4") \ No newline at end of file diff --git a/clase2/cuatin_daniel.py b/clase2/cuatin_daniel.py new file mode 100644 index 0000000..bfb2177 --- /dev/null +++ b/clase2/cuatin_daniel.py @@ -0,0 +1,116 @@ + +""" +La clase Heroe representa a un superhéroe con un nombre y un poder. +Tiene un método para presentarse. +Elegimos esta clase para ilustrar el concepto de clases en Python, es una forma +sencilla de entender cómo funcionan los objetos y métodos. +""" +# Ejercio 1: Definición de una clase Heroe +class Heroe: + def __init__(self, nombre, genero, identidad_secreta, poder): + self.nombre = nombre + self.genero = genero + self.identidad_secreta = identidad_secreta + self.poder = poder + + def presentar(self): + print(f"Soy {self.nombre} y tengo el poder de {self.poder}.", f"mi identidad secreta es {self.identidad_secreta}.") + + def to_json(self): + return { + "nombre": self.nombre, + "genero": self.genero, + "identidad_secreta": self.identidad_secreta, + "poder": self.poder + } + + + +# Ejercicio 2: Listas y diccionarios + +class Pelicula: + def __init__(self, titulo, director, anio): + self.titulo = titulo + self.director = director + self.anio = anio + + def mostrar_info(self): + print(f"{self.titulo} ({self.anio}), dirigido por {self.director}.") + + + +# Ejercicio 3: Trivia con POO + +class Pregunta: + def __init__(self, pregunta, opciones, respuesta_correcta): + self.pregunta = pregunta + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def verificar_respuesta(self, respuesta_usuario): + try: + return self.opciones[int(respuesta_usuario) - 1] == self.respuesta_correcta + except (ValueError, IndexError): + return False + +class Trivia: + def __init__(self): + self.preguntas = [] + + def agregar_pregunta(self, pregunta): + self.preguntas.append(pregunta) + + def iniciar_trivia(self): + for pregunta in self.preguntas: + print(pregunta.pregunta) + for i, opcion in enumerate(pregunta.opciones, 1): + print(f"{i}. {opcion}") + respuesta_usuario = input("Selecciona la opción correcta: ") + if pregunta.verificar_respuesta(respuesta_usuario): + print("¡Respuesta correcta!") + else: + print(f"Respuesta incorrecta. La respuesta correcta era: {pregunta.respuesta_correcta}") + +if __name__ == "__main__": + # Ejercicio 1: Crear un héroe y presentarlo + print("************ Ejercicio 1: Clase Heroe ************") + heroe = Heroe("Superman", "masculino", "Clark Kent", "Super fuerza") + heroe.presentar() + heroe.poder = "Volar" + heroe.presentar() + heroe_json = heroe.to_json() + print("Héroe en formato JSON:", heroe_json) + print("************ Fin del Ejercicio 1 ************\n") + print("************ Ejercicio 2: Lista de Películas ************") + # Ejercicio 2: Crear una lista de películas + peliculas = [ + Pelicula("Toy Story", "John Lasseter", 1995), + Pelicula("Forrest Gump", "Robert Zemeckis", 1994), + Pelicula("Insidious", "James Wan", 2010), + Pelicula("El Padrino", "Francis Ford Coppola", 1972), + ] + for pelicula in peliculas: + pelicula.mostrar_info() + print("************ Fin del Ejercicio 2 ************\n") + print("************ Ejercicio 3: Trivia ************") + # Ejercicio 3: Crear una trivia y iniciarla + trivia = Trivia() + pregunta1 = Pregunta( + "¿Cuál es la capital de Francia?", + ["Berlín", "Madrid", "París", "Roma"], + "París" + ) + trivia.agregar_pregunta(pregunta1) + pregunta2 = Pregunta( + "¿Cuál es el océano más grande del mundo?", + ["Atlántico", "Índico", "Ártico", "Pacífico"], + "Pacífico" + ) + trivia.agregar_pregunta(pregunta2) + pregunta3 = Pregunta( + "¿Quién escribió 'Cien años de soledad'?", + ["Gabriel García Márquez", "Mario Vargas Llosa", "Jorge Luis Borges", "Pablo Neruda"], + "Gabriel García Márquez" + ) + trivia.agregar_pregunta(pregunta3) + trivia.iniciar_trivia() diff --git a/clase2/edisontana.py b/clase2/edisontana.py new file mode 100644 index 0000000..1f1a2ed --- /dev/null +++ b/clase2/edisontana.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# tarea2.py +# +# Copyright 2025 edisontana +# +# Tarea 2. +# Ejercicio1: Defina un clase Pais con dos metodos +# Ejercicio2: Listas y diccionarios +# Ejercicio3: Trivia con POO + +from datetime import datetime + +class Pais: + + def __init__(self, nombreES, nombreEN, codigoISOA3): + """ + Crea un constructor + """ + self.nombreES = nombreES + self.nombreEN = nombreEN + self.codigoISOA3 = codigoISOA3 + + def verArea(self, pais): + """ + Visuliza el area superficial del pais + """ + # Diccionario de áreas de países (puedes expandir este diccionario) + self.areas = { + 'ecuador': 256370, + 'colombia': 1141748, + 'peru': 1285216, + 'argentina': 2780400, + 'chile': 756102 + } + + strPais = pais.lower() + if strPais in self.areas: + return self.areas[strPais] + else: + return f"No se encontró información para el país {pais}" + + + def verCapital(self, pais): + """ + Muestra la capital del pais + """ + self.capitales = { + 'ecuador': 'Quito', + 'colombia': 'Bogota', + 'peru': 'Lima', + 'argentina': 'Buenos Aires', + 'chile': 'Santiago' + } + strPais = pais.lower() + if strPais in self.capitales: + return self.capitales[strPais] + else: + return f"No se encontró información para el país {pais}" + +# Ejercicio2: Defina un clase Pais con dos metodos + +class Pelicula: + def __init__(self, anio, nombre, genero): + """ + Constructor de la clase Pelicula + + Args: + anio (int): Año de producción + nombre (str): Nombre de la pelicula + genero (str): Género de la pelicula + """ + self.anio = anio + self.nombre = nombre + self.genero = genero + + def __str__(self): + """ + Representación en cadena de la película + """ + return f"{self.nombre} ({self.anio}) - {self.genero}" + +class PeliculasFavoritas: + def __init__(self): + """ + Constructor de la clase PeliculasFavoritas + """ + self.peliculas = [] + + def agregapelicula(self, anio, nombre, genero): + """ + Agrega una nueva película a la lista + + Args: + anio (int): Año de producción + nombre (str): Nombre de la pelicula + genero (str): Género de la pelicula + """ + nuevapelicula = Pelicula(anio, nombre, genero) + self.peliculas.append(nuevapelicula) + print(f"Se agregó {nombre}") + + def buscaporanio(self, anio): + """ + Busca una pelicula por su año de producción + + Args: + anio (int): Año a buscar + + Returns: + Pelicula or str: Pelicula encontrada o mensaje de no encontrado + """ + for pelicula in self.peliculas: + if pelicula.anio == anio: + return pelicula + return f"No se encontró pelicula en el {anio}" + + def muestratodaspeliculas(self): + """ + Muestra todas las peliculas en la lista + """ + if not self.peliculas: + print("El catálogo está vacío.") + return 0 + + print("\n--- Catálogo de Películas ---") + for pelicula in self.peliculas: + print(pelicula) + +def main(): + """ + Función principal para demostrar el catálogo de películas + """ + # Crear instancia del catálogo + favorita1 = PeliculasFavoritas() + + # Agregar películas al catálogo + favorita1.agregapelicula(2010, "Inception", "Ciencia Ficción") + favorita1.agregapelicula(1972, "El Padrino", "Drama") + favorita1.agregapelicula(1999, "Matrix", "Ciencia Ficción") + + # Mostrar películas + favorita1.muestratodaspeliculas() + +# Ejercicio3: Defina un clase Pais con dos metodos +class Pregunta: + + def __init__(self, enunciado, opciones, respuesta): + """ + Constructor de la clase Pregunta + + Args: + enunciado (str): cadena de texto del enunciado + opciones (int): numero de opcion + respuesta (int): respuesta correcta + """ + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def __str__(self): + """ + Representación en cadena de la pregunta + """ + return f"{self.enunciado}" + + def visualizaopciones(self): + """ + Muestra las opciones de respuesta + """ + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificarespuesta(self, respuesta_usuario): + """ + Verifica si la respuesta del usuario es correcta + + Args: + respuesta_usuario (int): respuesta seleccionada por el usuario + + Returns: + bool: True si la respuesta es correcta, False en caso contrario + """ + # Ajustar el índice para que coincida con la lista (restar 1) + return respuesta_usuario - 1 == self.respuesta + + def obtienerespuestacorrecta(self): + """ + Devuelve la respuesta correcta + + Returns: + str: Opción correcta + """ + return self.opciones[self.respuesta] + +# Ejemplo de pregunta +def main3(): + # Crear una pregunta + pregunta1 = Pregunta( + "¿Cuál es la capital de Francia?", + ["Londres", "Berlín", "París", "Madrid"], + 2 # París es la respuesta correcta (índice 2) + ) + + # Mostrar la pregunta y sus opciones + pregunta1.visualizaopciones() + + # Solicitar respuesta del usuario + try: + respuestausuario = int(input("^.^ Ingrese el número de su respuesta: ")) + + # Verificar la respuesta + if pregunta1.verificarespuesta(respuestausuario): + print("¡Respuesta correcta!") + else: + print(f"Respuesta incorrecta. La respuesta correcta es: {pregunta1.obtienerespuestacorrecta()}") + + except ValueError: + print("Por favor, ingrese un número válido.") + +if __name__ == '__main__': + + print("Programa de la Tarea 2") + print("Realizado por 2025 Edison TANA") + print("Enunciado 1") + pais1 = Pais('Ecuador','Ecuador','ECU') + pais2 = Pais('Colombia','Colombia','COL') + print(f" >> Pais: {pais1.nombreES}") + print(pais1.verCapital(pais1.nombreES)) + print(f"{pais1.verArea(pais1.nombreES)} km²") + print(f" >> Pais: {pais2.nombreES}") + print(pais2.verCapital(pais2.nombreES)) + print(f"{pais2.verArea(pais2.nombreES)} km²") + print("Enunciado 2") + main() + print("Enunciado 3") + main3() + print("Fin del programa") diff --git a/clase2/erika_torres.py b/clase2/erika_torres.py new file mode 100644 index 0000000..321787d --- /dev/null +++ b/clase2/erika_torres.py @@ -0,0 +1,85 @@ +## 🧪 Ejercicio 1: Objetos + +class Bicicleta: + """ + Clase Bicicleta: + Representa una bicicleta con atributos básicos y métodos para simular su uso. + """ + def __init__(self, marca, tipo, color, velocidad_max): + self.marca = marca + self.tipo = tipo # Montaña, Ruta, Urbana, etc. + self.color = color + self.velocidad_max = velocidad_max + self.velocidad_actual = 0 + + def pedalear(self): + if self.velocidad_actual < self.velocidad_max: + self.velocidad_actual += 5 + print(f"Pedaleando... 🚴 Velocidad actual: {self.velocidad_actual} km/h") + else: + print("🚨 Has alcanzado la velocidad máxima.") + + def frenar(self): + if self.velocidad_actual > 0: + self.velocidad_actual -= 5 + print(f"Frenando... ⚠️ Velocidad actual: {self.velocidad_actual} km/h") + else: + print("La bicicleta ya está detenida.") + +# Crear objeto bicicleta +mi_bici = Bicicleta("Giant", "Montaña", "Roja", 25) + +# Usar métodos +mi_bici.pedalear() +mi_bici.pedalear() +mi_bici.frenar() + +## 🧪 Ejercicio 2: Listas y diccionarios + +# Lista de mis 3 películas favoritas +peliculas = ["El Origen", "Coco", "Intensamente"] + +# Diccionario con información de una de ellas +pelicula_favorita = { + "nombre": "El Origen", + "género": "Ciencia Ficción", + "año": 2010 +} + +# Operaciones +print("🎬 Mis películas favoritas son:", peliculas) +print("🎥 Detalles de la favorita:") +print("Nombre:", pelicula_favorita["nombre"]) +print("Género:", pelicula_favorita["género"]) +print("Año:", pelicula_favorita["año"]) + +## 🧪 Ejercicio 3: Trivia con PO + +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def mostrar(self): + print("❓", self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def responder(self, seleccion): + if self.opciones[seleccion - 1] == self.respuesta_correcta: + print("✅ ¡Correcto!") + else: + print(f"❌ Incorrecto. La respuesta era: {self.respuesta_correcta}") + +# Crear pregunta +pregunta1 = Pregunta( + "¿Cuál es la capital de Ecuador?", + ["Guayaquil", "Quito", "Cuenca"], + "Quito" +) + +# Mostrar y pedir respuesta +pregunta1.mostrar() +numero = int(input("Ingresa el número de tu respuesta: ")) +pregunta1.responder(numero) diff --git a/clase2/geomara_tambaco.py b/clase2/geomara_tambaco.py new file mode 100644 index 0000000..0acddc0 --- /dev/null +++ b/clase2/geomara_tambaco.py @@ -0,0 +1,197 @@ +""" +# Ejercicio 1: Objetos + +Objeto elegido: Celular +Como atributos hemos elegido: +Marca: +Modelo: +Color: +Almacenamiento: +peso: +Como método elegimos: +Mostrar la información +Encender +Apagar +Llamar +Enviar Mensajes +Instalar aplicaciones +""" +print(" -----EJERCICIO 1-----") +class Celular: + def __init__(self, marca, modelo,color,almacenamiento,peso): + self.marca = marca + self.modelo = modelo + self.color = color + self.almacenamiento = almacenamiento + self.peso = peso + + def mostrar_info(self): + print(f"Información general de tu celular") + print(f"Marca: {self.marca}") + print(f"Modelo: {self.modelo}") + print(f"Color: {self.color}") + print(f"Almacenamiento: {self.almacenamiento}") + print(f"Peso: {self.peso} gramos") + + def encender(self): + print(f"Tu celular {self.marca} está encendido") + + def apagar(self): + print(f"Tu celular {self.modelo} se va apagar") + + def llamar(self): + print(f"Llamando a Juan López desde tu celular {self.marca} ") + + def enviar(self): + print(f"Mensaje enviado a Valeria desde un celular {self.modelo} de color {self.color}") + + def instalar_app(self): + print(f"Tu celular tiene {self.almacenamiento} ocupados. No hay espacio disponible. ") + + + +celular1 = Celular("Samsung", "Galaxy S24", "Gris", "256 GB", 233) +celular2 = Celular("Apple", "iPhone 15 Pro", "Negro espacial", "512 GB", 221) +celular3 = Celular("Xiaomi", "Redmi Note 13", "Azul", "128 GB", 205) +celular4 = Celular("Motorola", "Edge 50 Pro", "Verde bosque", "256 GB", 186) +celular5 = Celular("Google", "Pixel 8", "Rosa", "128 GB", 187) +celular6 = Celular("OnePlus", "12R", "Negro mate", "256 GB", 207) + + +# Lista con los celulares +lista_celulares = [celular1, celular2, celular3, celular4, celular5, celular6] + +# Función para obtener el peso promedio +def peso_promedio(celulares): + total = sum(celular.peso for celular in celulares) + return total / len(celulares) + +# Mostrar resultado +print(f"El peso promedio de los celulares es: {peso_promedio(lista_celulares):.2f} gramos") + +celular1.mostrar_info() +celular2.encender() +celular3.apagar() +celular4.llamar() +celular5.enviar() +celular6.instalar_app() + +""" +Ejercicio 2 +## Ejercicio 2: Listas y diccionarios + +Crea: +- Una lista con tus 3 películas favoritas. +- Un diccionario con su nombre, genero, año. +- Imprime las operaciones. + +--- + +""" +print(" -----EJERCICIO 2-----") + +lista_peliculas=["El gato con botas", "Chespirito","Alicia en el país de mas maravillas"] + +# Agrega al final +lista_peliculas.append("Avatar") +# Inserta en posición 1 +lista_peliculas.insert(1, "Titanic") +# Mostrar cuántas películas hay +print(f"\nTotal de películas: {len(lista_peliculas)}") +# Ordenar alfabéticamente +lista_peliculas.sort() +# Eliminar una película si existe +if "Chespirito" in lista_peliculas: + lista_peliculas.remove("Chespirito") + +#Imprimimos la lista +for i, pelicula in enumerate(lista_peliculas, start=1): + print(f"{i}. {pelicula}") + + + +diccionario_peliculas = [{ + "nombre":"El gato con botas", + "género":"Comedia", + "año":2005 +}, +{ "nombre":"Chespirito", + "género":"Drama", + "año":2025 +}, +{ + "nombre":"Alicia en el país de las maravillas", + "género":"Comedia", + "año":200 +} +] + + +diccionario_peliculas = [ + { + "nombre": "El gato con botas", + "género": "Comedia", + "año": 2005 + }, + { + "nombre": "Chespirito", + "género": "Drama", + "año": 2025 + }, + { + "nombre": "Alicia en el país de las maravillas", + "género": "Comedia", + "año": 2000 } +] + +for pelicula in diccionario_peliculas: + print("." * 30) + print(f"Nombre: {pelicula['nombre']}") + print(f"Género: {pelicula['género']}") + print(f"Año: {pelicula['año']}") + +print(" -----EJERCICIO 3-----") + +class Pregunta: + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar(self): + print("\n" + self.enunciado) + for i, opcion in enumerate(self.opciones): + print(f"{i + 1}. {opcion}") + seleccion = int(input("Seleccione una opción (1-{}): ".format(len(self.opciones)))) + return seleccion - 1 + + def es_correcta(self, seleccion_usuario): + return seleccion_usuario == self.respuesta + + +preguntas = [ + Pregunta("¿Cuál es la capital de Ecuador?", ["Quito", "Guayaquil", "Cuenca", "Loja"], 0), + Pregunta("¿Cuál es el río más largo de Ecuador?", ["Río Esmeraldas", "Río Napo", "Río Guayas", "Río Pastaza"], 1), + Pregunta("¿En qué año se independizó Ecuador?", ["1822", "1810", "1820", "1830"], 0), + Pregunta("¿Cuál es el volcán más alto de Ecuador?", ["Cotopaxi", "Chimborazo", "Tungurahua", "Sangay"], 1), +] + +indice = 0 + +while indice < len(preguntas): + pregunta = preguntas[indice] + seleccion = pregunta.mostrar() + + if pregunta.es_correcta(seleccion): + print("¡Correcto!") + else: + correcta = pregunta.opciones[pregunta.respuesta] + print(f"Incorrecto. La respuesta correcta era: {correcta}") + + continuar = input("\n¿Quieres responder otra pregunta? (s/n): ").lower() + if continuar != "s": + break + + indice += 1 + + diff --git a/clase2/george_penafiel_clase2.py b/clase2/george_penafiel_clase2.py new file mode 100644 index 0000000..c3e814d --- /dev/null +++ b/clase2/george_penafiel_clase2.py @@ -0,0 +1,62 @@ +# Clase 2 - GEORGE ANTHONY PEÑAFIEL ALVARADO + +# 🧪 Ejercicio 1: Objetos +print("\n--- EJERCICIO 1: OBJETOS ---") +class Celular: + def __init__(self, marca, modelo, año, color): + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + + def llamar(self, numero): + return f"Llamando al {numero} desde un {self.marca} {self.modelo}" + + def enviar_mensaje(self, mensaje): + return f"Mensaje enviado: {mensaje}" + +mi_celular = Celular("Samsung", "Galaxy A52", 2021, "Negro") +print(mi_celular.llamar("0999999999")) +print(mi_celular.enviar_mensaje("Hola, ¿cómo estás?")) + +# 🧪 Ejercicio 2: Listas y Diccionarios +print("\n--- EJERCICIO 2: LISTAS Y DICCIONARIOS ---") +peliculas = ["Interestelar", "Inception", "El origen"] +info = { + "nombre": "Juan", + "genero": "Masculino", + "año": 2000 +} +print("Películas favoritas:", peliculas) +print("Información personal:", info) +print("Primera película:", peliculas[0]) +print("Nombre del usuario:", info["nombre"]) + +# 🧪 Ejercicio 3: Trivia con POO +print("\n--- EJERCICIO 3: TRIVIA ---") +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def mostrar(self): + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def responder(self, respuesta_usuario): + if self.opciones[respuesta_usuario - 1] == self.respuesta_correcta: + print("¡Correcto!") + else: + print("Incorrecto. La respuesta correcta era:", self.respuesta_correcta) + +pregunta1 = Pregunta( + "¿Cuál es el planeta más grande del sistema solar?", + ["Tierra", "Marte", "Júpiter", "Venus"], + "Júpiter" +) + +pregunta1.mostrar() +respuesta = int(input("Selecciona una opción (1-4): ")) +pregunta1.responder(respuesta) diff --git a/clase2/jazmin_rodriguez.py b/clase2/jazmin_rodriguez.py new file mode 100644 index 0000000..9e1f2bd --- /dev/null +++ b/clase2/jazmin_rodriguez.py @@ -0,0 +1,63 @@ +class Animal: + def __init__(self, tipo, nombre=""): + self.tipo = tipo + self.nombre = nombre + + def correr(self): + if self.tipo == "Felino": + print(f"El felino {self.nombre} corre más rápido") + elif self.tipo == "Canino": + print(f"El canino {self.nombre} corre con resistencia") + elif self.tipo == "Ave": + print(f"El ave {self.nombre} vuela en lugar de correr") + + def alimentar(self): + if self.tipo == "Felino": + print(f"El felino {self.nombre} come carne") + elif self.tipo == "Canino": + print(f"El canino {self.nombre} come croquetas") + elif self.tipo == "Ave": + print(f"El ave {self.nombre} come semillas") + + def object(self): + return { + "tipo": self.tipo, + "nombre": self.nombre, + } + + def cambiar_nombre(self, nuevo_nombre): + self.nombre = nuevo_nombre + +class Felino(Animal): + def __init__(self, nombre): + super().__init__("Felino", nombre) + +class Canino(Animal): + def __init__(self, nombre): + super().__init__("Canino", nombre) + +if __name__ == "__main__": + + tigre = Animal("Felino", "Tigre") + tigre.correr() + lobo = Animal("Canino", "Lobo") + lobo.correr() + aguila = Animal("Ave") + aguila.correr() + + leon = Felino("León") + leon.correr() + leon.alimentar() + perro = Canino("Perro") + perro.alimentar() + lobo.cambiar_nombre("Lobo de Montaña") + print("Lobo actualizado:", lobo.nombre) + lobo_objeto_json = lobo.object() + nombre_lobo = lobo_objeto_json["nombre"] + print("Lobo en formato JSON:", lobo_objeto_json) + print("Lobo en formato JSON nombre:", nombre_lobo) + lobo_objeto_json["nombre"] = "Lobo de la Noche" + lobo_objeto_json["tipo"] = "Perro salvaje" + nuevo_lobo = lobo_objeto_json["nombre"] + print("nuevo lobo:", lobo_objeto_json["tipo"]) + diff --git a/clase2/jorge_guato.py b/clase2/jorge_guato.py new file mode 100644 index 0000000..a3b23bd --- /dev/null +++ b/clase2/jorge_guato.py @@ -0,0 +1,233 @@ +# Ejercicio 1: Objetos - Libro +class Libro: + """ + Clase Libro que representa un libro con sus características básicas. + + Atributos: + - titulo: Nombre del libro + - autor: Autor del libro + - año: Año de publicación + - genero: Género literario + - paginas: Número de páginas + - leido: Estado de lectura (True/False) + + Métodos: + - leer(): Marca el libro como leído + - obtener_info(): Muestra información del libro + - es_clasico(): Determina si es un libro clásico (más de 50 años) + """ + + def __init__(self, titulo, autor, año, genero, paginas): + self.titulo = titulo + self.autor = autor + self.año = año + self.genero = genero + self.paginas = paginas + self.leido = False + + def leer(self): + """Marca el libro como leído""" + self.leido = True + print(f"Has terminado de leer '{self.titulo}'") + + def obtener_info(self): + """Muestra la información completa del libro""" + estado = "Leído" if self.leido else "No leído" + return f""" + Título: {self.titulo} + Autor: {self.autor} + Año: {self.año} + Género: {self.genero} + Páginas: {self.paginas} + Estado: {estado} + """ + + def es_clasico(self): + """Determina si el libro es clásico (más de 50 años)""" + from datetime import datetime + año_actual = datetime.now().year + return (año_actual - self.año) > 50 + +def ejercicio1(): + """Ejercicio 1: Crear y usar objetos Libro""" + print("=" * 50) + print("EJERCICIO 1: OBJETOS - LIBRO") + print("=" * 50) + + # Crear objetos libro + libro1 = Libro("Cien años de soledad", "Gabriel García Márquez", 1967, "Realismo mágico", 432) + libro2 = Libro("1984", "George Orwell", 1949, "Distopía", 328) + libro3 = Libro("El Principito", "Antoine de Saint-Exupéry", 1943, "Infantil", 96) + + # Realizar operaciones + print("Información inicial de los libros:") + print(libro1.obtener_info()) + print(libro2.obtener_info()) + print(libro3.obtener_info()) + + # Leer algunos libros + libro1.leer() + libro3.leer() + + # Verificar si son clásicos + print(f"\n¿'{libro1.titulo}' es clásico? {libro1.es_clasico()}") + print(f"¿'{libro2.titulo}' es clásico? {libro2.es_clasico()}") + print(f"¿'{libro3.titulo}' es clásico? {libro3.es_clasico()}") + + print("\n**Explicación del objeto Libro:**") + print("Elegí el objeto Libro porque es fácil de entender y útil para gestionar una biblioteca personal.") + print("Permite almacenar información importante como título, autor, año, género y páginas.") + print("Los métodos permiten interactuar con el libro: marcarlo como leído, obtener información y verificar si es clásico.") + +def ejercicio2(): + """Ejercicio 2: Listas y diccionarios""" + print("\n" + "=" * 50) + print("EJERCICIO 2: LISTAS Y DICCIONARIOS") + print("=" * 50) + + # Lista con 3 películas favoritas + peliculas_favoritas = ["El Padrino", "Pulp Fiction", "Forrest Gump"] + + # Diccionario con información de cada película (nombre, género, año) + informacion_peliculas = { + "El Padrino": { + "genero": "Drama", + "año": 1972 + }, + "Pulp Fiction": { + "genero": "Crimen", + "año": 1994 + }, + "Forrest Gump": { + "genero": "Drama", + "año": 1994 + } + } + + # Imprimir operaciones + print("Mis 3 películas favoritas:") + for i, pelicula in enumerate(peliculas_favoritas, 1): + print(f"{i}. {pelicula}") + + print(f"\nPrimera película favorita: {peliculas_favoritas[0]}") + print(f"Última película favorita: {peliculas_favoritas[-1]}") + print(f"Total de películas: {len(peliculas_favoritas)}") + + print("\nInformación detallada de cada película:") + for pelicula in peliculas_favoritas: + info = informacion_peliculas[pelicula] + print(f"\n🎬 {pelicula}:") + print(f" Género: {info['genero']}") + print(f" Año: {info['año']}") + + print("\nOperaciones con el diccionario:") + print(f"Película más antigua: {min(informacion_peliculas.items(), key=lambda x: x[1]['año'])[0]}") + print(f"Película más reciente: {max(informacion_peliculas.items(), key=lambda x: x[1]['año'])[0]}") + + # Contar géneros + generos = [info['genero'] for info in informacion_peliculas.values()] + print(f"Géneros: {', '.join(set(generos))}") + +# Ejercicio 3: Trivia con POO +class Pregunta: + """ + Clase Pregunta para crear preguntas de trivia. + + Atributos: + - enunciado: La pregunta a realizar + - opciones: Lista de opciones posibles + - respuesta: Número de la opción correcta (1-4) + """ + + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar_pregunta(self): + """Muestra la pregunta y sus opciones""" + print(f"\n{self.enunciado}") + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar_respuesta(self, respuesta_usuario): + """Verifica si la respuesta del usuario es correcta""" + return respuesta_usuario == self.respuesta + +def ejercicio3(): + """Ejercicio 3: Trivia con POO""" + print("\n" + "=" * 50) + print("EJERCICIO 3: TRIVIA CON POO") + print("=" * 50) + + # Crear preguntas de trivia + preguntas = [ + Pregunta( + "¿Cuál es la capital de Ecuador?", + ["Guayaquil", "Quito", "Cuenca", "Ambato"], + 2 + ), + Pregunta( + "¿En qué año se fundó Python?", + ["1989", "1991", "1995", "2000"], + 2 + ), + Pregunta( + "¿Cuál es el planeta más grande del sistema solar?", + ["Tierra", "Marte", "Júpiter", "Saturno"], + 3 + ) + ] + + puntuacion = 0 + total_preguntas = len(preguntas) + + print("¡Bienvenido a la trivia!") + print(f"Responde las siguientes {total_preguntas} preguntas:") + + for i, pregunta in enumerate(preguntas, 1): + print(f"\nPregunta {i}:") + pregunta.mostrar_pregunta() + + try: + respuesta = int(input("Tu respuesta (1-4): ")) + if 1 <= respuesta <= 4: + if pregunta.verificar_respuesta(respuesta): + print("¡Correcto! ✓") + puntuacion += 1 + else: + print(f"Incorrecto. La respuesta correcta era: {pregunta.respuesta}") + else: + print("Opción inválida. Se considera incorrecta.") + except ValueError: + print("Por favor, ingresa un número del 1 al 4.") + + print(f"\n¡Trivia terminada!") + print(f"Puntuación final: {puntuacion}/{total_preguntas}") + if puntuacion == total_preguntas: + print("¡Excelente! Respondiste todas correctamente.") + elif puntuacion >= total_preguntas // 2: + print("¡Bien hecho! Tienes un buen conocimiento.") + else: + print("Sigue estudiando, puedes mejorar.") + +def main(): + """Función principal que ejecuta todos los ejercicios""" + print("🎯 PROGRAMA DE EJERCICIOS DE PROGRAMACIÓN") + print("=" * 60) + + # Ejecutar Ejercicio 1: Objetos + ejercicio1() + + # Ejecutar Ejercicio 2: Listas y Diccionarios + ejercicio2() + + # Ejecutar Ejercicio 3: Trivia con POO + ejercicio3() + + print("\n" + "=" * 60) + print("🎉 ¡TODOS LOS EJERCICIOS COMPLETADOS!") + print("=" * 60) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/clase2/jorge_luis_castellanos.py b/clase2/jorge_luis_castellanos.py new file mode 100644 index 0000000..4fcd00d --- /dev/null +++ b/clase2/jorge_luis_castellanos.py @@ -0,0 +1,111 @@ +#Tarea Dos +#____________________________________________________________ +#Ejercicio número 1 +#Ejercicios de tuplas, listas y diccionarios +#____________________________________________________________ + +class automovil: + def __init__(self): + self.marca = "" + self.modelo = "" + self.anio = "" + self.color = "" + + def __init__(self,marca,modelo,anio,color): + self.marca = marca + self.modelo = modelo + self.anio = anio + self.color = color + + def informacion(self): + print(f"Marca: {self.marca} Modelo: {self.modelo} Año: {self.anio} Color: {self.color}") + + def aceleracion(self): + print(f"El auto {self.marca} {self.modelo}, tiene un tiempo de aceleracion de 5 segundos de 0/100 Km") + + def cantidad_pasajeros(self): + print(f"El auto {self.marca} {self.modelo}, tiene la capacidad de 5 pasajeros") + + def sonido(self): + print(f"El auto {self.marca} {self.modelo} posee android car y Apple Car, con Spotify") + + def seguridad(self): + print(f"El auto {self.marca} {self.modelo} posee camaras 360° y graba todo el recorrido del viaje") + +#____________________________________________________________ +#Ejercicio número 2 +#Creación de un juego de trivia +#____________________________________________________________ +class Pregunta: + opciones = [] + def __init__(self,pregunta,respuesta,opciones): + self.pregunta = pregunta + self.opciones = list(opciones) + self.respuesta = respuesta + + def mostrar_pregunta(self): + print(f" {self.pregunta} : ") + indice = 1 + for opcion in self.opciones: + print(f" {indice} {opcion}") + indice += 1 + + def validar_respuesta(self,respuesta_usuario): + if self.respuesta == respuesta_usuario: + return True + else: + return False + + +if __name__ == "__main__": + + #Ejercicio número 1 + print("Caracteristicas de Automovil") + automovil = automovil("Mazda","CX-30","2025","rojo") + automovil.informacion() + automovil.aceleracion() + automovil.cantidad_pasajeros() + automovil.sonido() + automovil.seguridad() + print("\n") + + print("Listas y Diccionarios") + pelicula_1 = {"Nombre":"Lord of the rings : La comunidad del anillo","genero":"acción","Anio":2001} + pelicula_2 = {"Nombre":"Lord of the rings : Las dos torres","genero":"acción","Anio":2002} + pelicula_3 = {"Nombre":"Lord of the rings : El retorno del rey","genero":"drama","Anio":2023} + + Listado = [pelicula_1, pelicula_2, pelicula_3] + + for pelicula in Listado: + print(pelicula) + + pelicula_3["genero"]="accion" + pelicula_3["Anio"] = 2003 + + pelicula_4 = {"Nombre":"El hobbit : Un viaje inesperado","genero":"accion","Anio":2012} + + Listado.append(pelicula_4) + Listado.remove(pelicula_3) + + print("\n") + print("Listado despues de eliminar pelicula 3 y posicionar pelicula 4") + print("\n") + + for pelicula in Listado: + print(pelicula) + + print("\n") + + + #Ejercicio número 2 + print("Trivia") + pregunta = Pregunta("Cuál es la primera pelicula de Lord of the rings", 2, ["EL retorno del rey","La comunindad del anillo","Las dos torres","Un viaje inesperado"]) + + pregunta.mostrar_pregunta() + + respuesta_correcta = int(input("Su respuesta es (ingrese el número correspondiente):")) + + if pregunta.validar_respuesta(respuesta_correcta): + print("Respuesta correcta") + else: + print("Respuesta Incorrecta") \ No newline at end of file diff --git a/clase2/milton_chiluisa.py b/clase2/milton_chiluisa.py new file mode 100644 index 0000000..4f857ff --- /dev/null +++ b/clase2/milton_chiluisa.py @@ -0,0 +1,154 @@ +class Celular: + + + def __init__(self, marca, modelo, año, color): + + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + print(f"¡Nuevo celular {self.marca} {self.modelo} ({self.color}) del año {self.año} creado!") + + def llamar(self, numero_destino): + + print(f"Realizando llamada desde el {self.modelo} ({self.color}) a {numero_destino}...") + return f"Llamada a {numero_destino} en curso." + + def enviar_mensaje(self, numero_destino, mensaje): + + print(f"Enviando mensaje desde el {self.modelo} ({self.color}) a {numero_destino}: '{mensaje}'") + return f"Mensaje enviado a {numero_destino}." + + def obtener_info(self): + + return f"Marca: {self.marca}, Modelo: {self.modelo}, Año: {self.año}, Color: {self.color}" + +# --- Operaciones con el Objeto Celular --- + +if __name__ == "__main__": + print("--- Creando objetos Celular ---") + + # Crear una instancia (objeto) de la clase Celular + mi_celular = Celular("Samsung", "Galaxy S23", 2023, "Negro") + celular_amigo = Celular("Apple", "iPhone 14 Pro", 2022, "Gris Espacial") + + print("\n--- Accediendo a atributos ---") + print(f"Mi celular es un {mi_celular.marca} {mi_celular.modelo}.") + print(f"El celular de mi amigo es de color {celular_amigo.color}.") + + print("\n--- Realizando operaciones (llamando a métodos) ---") + + # Realizar una llamada con mi_celular + resultado_llamada = mi_celular.llamar("0991234567") + print(f"Estado: {resultado_llamada}") + + # Enviar un mensaje con celular_amigo + resultado_mensaje = celular_amigo.enviar_mensaje("0987654321", "Hola, ¿cómo estás?") + print(f"Estado: {resultado_mensaje}") + + # Obtener información completa de mi_celular + info_mi_celular = mi_celular.obtener_info() + print(f"\nInformación de mi celular: {info_mi_celular}") + + # Obtener información completa de celular_amigo + info_celular_amigo = celular_amigo.obtener_info() + print(f"Información del celular de mi amigo: {info_celular_amigo}") + + print("\n--- Modificando un atributo ---") + mi_celular.color = "Verde Oscuro" + print(f"He cambiado el color de mi celular a {mi_celular.color}.") + print(f"Nueva información de mi celular: {mi_celular.obtener_info()}") + + + + + + + + + # Ejercicio 2: Listas y Diccionarios + +# --- Parte 1: Crear una lista con tus 3 películas favoritas --- +# Una lista es una colección ordenada y mutable de elementos. +# Los elementos pueden ser de diferentes tipos de datos. +peliculas_favoritas = [ + "Interstellar", + "El Señor de los Anillos: La Comunidad del Anillo", + "Origen" +] + +print("--- Mis 3 películas favoritas ---") +print(f"Lista de películas: {peliculas_favoritas}") + + +print("\n--- Operaciones con la lista de películas ---") + + +print(f"Mi primera película favorita es: {peliculas_favoritas[0]}") +print(f"Mi tercera película favorita es: {peliculas_favoritas[2]}") + + +peliculas_favoritas.append("Pulp Fiction") +print(f"Lista después de añadir 'Pulp Fiction': {peliculas_favoritas}") + + +peliculas_favoritas.remove("Origen") +print(f"Lista después de eliminar 'Origen': {peliculas_favoritas}") + + +print(f"Número total de películas en la lista: {len(peliculas_favoritas)}") + + +print("Recorriendo mis películas favoritas:") +for pelicula in peliculas_favoritas: + print(f"- {pelicula}") + + +# --- Parte 2: Crear un diccionario con tu nombre, género y año --- + +informacion_personal = { + "nombre": "Milton", + "genero": "Masculino", + "año_nacimiento": 1990 +} + +print("\n--- Mi información personal ---") +print(f"Diccionario de información: {informacion_personal}") + + +print("\n--- Operaciones con el diccionario de información ---") + + +print(f"Mi nombre es: {informacion_personal['nombre']}") +print(f"Mi género es: {informacion_personal['genero']}") + + +informacion_personal["año_nacimiento"] = 1992 +print(f"Año de nacimiento actualizado: {informacion_personal['año_nacimiento']}") +print(f"Diccionario después de actualizar el año: {informacion_personal}") + +informacion_personal["ciudad"] = "Quito" +print(f"Diccionario después de añadir la ciudad: {informacion_personal}") + + +del informacion_personal["genero"] +print(f"Diccionario después de eliminar el género: {informacion_personal}") + + +print(f"Claves del diccionario: {informacion_personal.keys()}") + + +print(f"Valores del diccionario: {informacion_personal.values()}") + + +print("Recorriendo las claves de mi información:") +for clave in informacion_personal: + print(f"- {clave}: {informacion_personal[clave]}") + + +print("Recorriendo pares clave-valor de mi información:") +for clave, valor in informacion_personal.items(): + print(f"- {clave}: {valor}") + + + \ No newline at end of file diff --git a/clase2/pablo_colcha.py b/clase2/pablo_colcha.py new file mode 100644 index 0000000..61f7385 --- /dev/null +++ b/clase2/pablo_colcha.py @@ -0,0 +1,98 @@ +""" Crea: +- El objeto que definiste en clase y realiza operaciones con el. +- Explicar que es el objeto que hace y el proque de la elección""" + + +class Celular: + + def __init__(self, marca, modelo, anio, color): + self.marca = marca + self.modelo = modelo + self.anio = anio + self.color = color + + def llamar(self, numero): + print(f"Llamando al número {numero} desde un {self.marca} {self.modelo}...") + + def enviar_mensaje(self, numero, mensaje): + print(f"Enviando mensaje a {numero}: {mensaje}") + + +# Crear objeto celular +celular = Celular("Samsung", "Galaxy S22", 2022, "Negro") + +# Operaciones con el objeto +celular.llamar("0998765432") +celular.enviar_mensaje("0998765432", "Hola, ¿cómo estás?") + + +"""Ejercicio 2: Listas y diccionarios + +Crea: +- Una lista con tus 3 películas favoritas. +- Un diccionario con tu nombre, genero, año. +- Imprime las operaciones.""" + + +# 🎬 Lista de 3 películas favoritas, cada una como un diccionario +p_favoritas = [ + {"nombre": "El señor de los anillos", "genero": "Fantasía", "año": 2001}, + {"nombre": "Avatar", "genero": "Ciencia ficción", "año": 2009}, + {"nombre": "Inception", "genero": "Acción / Ciencia ficción", "año": 2010} +] + +# 🔹 Imprimir cada película con su información +print(" Información de mis 3 películas favoritas:\n") +for pelicula in p_favoritas: + print(f"Nombre: {pelicula['nombre']}") + print(f"Género: {pelicula['genero']}") + print(f"Año: {pelicula['año']}") + print("-" * 30) # línea separadora + + +""" Ejercicio 3: Trivia con POO + +1. Crea una clase `Pregunta` con `enunciado`, `opciones` y `respuesta`. +numero = int(input("Ingrese número: ")) +2. Muestra la pregunta y permite al usuario responder. +3. Indica si la respuesta fue correcta o no.""" + + +class Pregunta: + + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar(self): + print("\n Pregunta:") + print(self.enunciado) + for i, opcion in enumerate(self.opciones): + print(f"{i + 1}. {opcion}") + + def verificar(self, eleccion): + return eleccion - 1 == self.respuesta + + +# Crear una pregunta +pregunta1 = Pregunta( + "¿A qué altitud se encuentra Quito?", + ["1000", "2850", "500", "4000"], + 1 # 2850 es la respuesta correcta (índice 1) +) + +# Mostrar la pregunta +pregunta1.mostrar() + +# Solicitar respuesta del usuario +try: + numero = int(input("Ingrese el número de su respuesta: ")) + if pregunta1.verificar(numero): + print("¡Respuesta correcta!") + else: + print(" Respuesta incorrecta.") +except ValueError: + print(" Entrada no válida. Debes ingresar un número.") + + diff --git a/clase2/readme.md b/clase2/readme.md new file mode 100644 index 0000000..add91c3 --- /dev/null +++ b/clase2/readme.md @@ -0,0 +1,64 @@ +# Clase 2 – Estructuras y POO + +## 🎯 Objetivo: +Aplicar estructuras de datos y Programación Orientada a Objetos para crear una trivia interactiva. + +--- + +## 📋 Instrucciones: + +1. Usa el repositorio que ya forkeaste. + +2. Crea un archivo `nombre_apellido.py` en la carpeta `clase_2`. +3. Resuelve los ejercicios. +4. Haz commit, push y un Pull Request con el título:\ + **"Clase 2 - TuNombre TuApellido"** + +2. Crea un archivo nombre_apellido.py en la carpeta clase_2. +3. Resuelve los ejercicios. +4. Haz commit, push y un Pull Request con el título:\ + *"Clase 2 - TuNombre TuApellido"* + +--- + +## 🧪 Ejercicio 1: Objetos + + + +Crea: +- El objeto que definiste en clase y realiza operaciones con el. +- Explicar que es el objeto que hace y el proque de la elección + +--- +# Como documentar en python para el deber +""" +Celular: +- Marca +- Modelo +- Año +- Color +Metodos: +- Llamar +- Enviar mensaje +""" + +## 🧪 Ejercicio 2: Listas y diccionarios + +Crea: +- Una lista con tus 3 películas favoritas. +- Un diccionario con nombre, genero, año. +- Imprime las operaciones. + +--- + +## 🧪 Ejercicio 3: Trivia con POO + +1. Crea una clase `Pregunta` con `enunciado`, `opciones` y `respuesta`. +numero = int(input("Ingrese número: ")) +2. Muestra la pregunta y permite al usuario responder. +3. Indica si la respuesta fue correcta o no. + +1. Crea una clase Pregunta con enunciado, opciones y respuesta. +numero = int(input("Ingrese número: ")) +2. Muestra la pregunta y permite al usuario responder. +3. Indica si la respuesta fue correcta o no. diff --git a/clase2/ronald_diaz.py b/clase2/ronald_diaz.py new file mode 100644 index 0000000..badfa6d --- /dev/null +++ b/clase2/ronald_diaz.py @@ -0,0 +1,93 @@ +""" +Ejercicio1 +Clase: cuenta bancaria +Atributos: titular, numero_cuenta, saldo +Metodos: depositar, retirar, consultar_saldo +""" + +class CuentaBancaria: + + def __init__(self, titular, numero_cuenta, saldo= 0.0): + self.titular = titular + self.numero_cuenta = numero_cuenta + self.saldo = float(saldo) + + def depositar(self, monto): + if monto <= 0: + print("El monto a depositar debe ser mayor que cero.") + self.saldo += monto + print(f"Depósito exitoso: +{monto:.2f}. Saldo actual: {self.saldo:.2f}") + + def retirar(self, monto): + if monto <= 0: + print("El monto a retirar debe ser mayor que cero.") + elif monto > self.saldo: + print("Fondos insuficientes para realizar el retiro.") + else: + self.saldo -= monto + print(f"Retiro exitoso: -{monto:.2f}. Saldo actual: {self.saldo:.2f}") + + def consultar_saldo(self) -> float: + return self.saldo +"""Ejercicio 2 +Listas y diccionarios +""" +lista_pelis = ["Pokemon", "Shrek", "Los Pitufos"] + +#impresion de los elementos de la lista +print("Listado de peliculas") +for elemento in lista_pelis: + print(f"- {elemento}") + +#Diccionario de datos +misDatos = { + "nombre" : "Ronald", + "edad" : 30, + "genero" : "Masculino" +} +#Impresion de los datos del diccionario +print("Mis datos:") +print(f"Nombre: {misDatos["nombre"]} Edad: {misDatos["edad"]} Genero: {misDatos["genero"]}") + +""" +Ejercicio 3 Trivia con POO +1. Crea una clase `Pregunta` con `enunciado`, `opciones` y `respuesta`. +2. Muestra la pregunta y permite al usuario responder. +3. Indica si la respuesta fue correcta o no. +""" +class Pregunta: + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar(self) -> None: + print(self.enunciado) + numeros = range(1, len(self.opciones)+1) + for numero, opcion in zip(numeros, self.opciones): + print(f" {numero}. {opcion}") + + def preguntar(self) -> bool: + self.mostrar() + respuesta_usuario = int(input("Tu respuesta (1,2,3....): ")) + if respuesta_usuario == self.respuesta: + print("¡Correcto!") + return True + else: + print(f"Incorrecto. La respuesta correcta era {self.respuesta}.") + return False + +if __name__ == "__main__": + #Ejercicio 1 + cuenta = CuentaBancaria("Armando Lopez", "1700098563", 100.0) + cuenta.depositar(150.0) + cuenta.retirar(75.0) + print(f"Saldo actual: {cuenta.consultar_saldo()}") + #El ejericicio 2 ya se ejecuta sin llamarlo + # Ejercicio 3 + q = Pregunta( + "¿Cuál es la capital de Ecuador?", + ["Madrid", "Berlín", "Quito", "Roma"], + 3 + ) + q.preguntar() \ No newline at end of file diff --git a/clase2/santiago_calvopina.py b/clase2/santiago_calvopina.py new file mode 100644 index 0000000..fc1d3fc --- /dev/null +++ b/clase2/santiago_calvopina.py @@ -0,0 +1,103 @@ +# ////////////////////////////////// Ejercicio 1: Objetos ////////////////////////////////// + +# Objeto: Computadora + +""" Atributos: +- marca: fabricante de la computadora +- sistema_operativo: sistema operativo instalado +- ram: memoria RAM en GB +- almacenamiento: capacidad del disco en GB + +Métodos: +- encender(): imprime que la computadora está encendida +- apagar(): imprime que la computadora se está apagando +- mostrar_info(): muestra detalles de la computadora + +Este objeto fue elegido porque es algo que usamos a diario y es fácil de relacionar con atributos y acciones reales. """ + + + +class Computadora: + def __init__(self, marca, sistema_operativo, ram, almacenamiento): + self.marca = marca + self.sistema_operativo = sistema_operativo + self.ram = ram + self.almacenamiento = almacenamiento + + def encender(self): + print(f"La computadora {self.marca} se está encendiendo...") + + def apagar(self): + print(f"La computadora {self.marca} se está apagando...") + + def mostrar_info(self): + print(f"Marca: {self.marca}") + print(f"Sistema Operativo: {self.sistema_operativo}") + print(f"RAM: {self.ram} GB") + print(f"Almacenamiento: {self.almacenamiento} GB") + +# ////////////////////////////////// Ejercicio 2: Listas y Diccionarios ////////////////////////////////// + +peliculas_favoritas = ["Interestelar", "Coco", "Matrix"] + +info_peliculas = [ + {"titulo": "Interestelar", "genero": "Ciencia Ficción", "anio": 2014}, + {"titulo": "Coco", "genero": "Animación", "anio": 2017}, + {"titulo": "Matrix", "genero": "Acción", "anio": 1999} +] + +print("\n Mis películas favoritas:") +print(peliculas_favoritas) + +print("\n Información de las películas:") +for peli in info_peliculas: + print(peli) + +# Operaciones +print("\n Operaciones con diccionarios:") +info_peliculas[1]["anio"] = 2018 +nueva_pelicula = {"titulo": "Inception", "genero": "Ciencia Ficción", "anio": 2010} +info_peliculas.append(nueva_pelicula) +info_peliculas.pop(0) + +print("Después de las modificaciones:") +for peli in info_peliculas: + print(peli) + +# ////////////////////////////////// Ejercicio 3: Trivia con POO ////////////////////////////////// + +class Pregunta: + def __init__(self, enunciado, opciones, respuesta_correcta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta_correcta = respuesta_correcta + + def mostrar(self): + print(f"\n {self.enunciado}") + for i, opcion in enumerate(self.opciones, start=1): + print(f"{i}. {opcion}") + + def verificar(self, eleccion_usuario): + return eleccion_usuario == self.respuesta_correcta + +# Pregunta +pregunta = Pregunta( + "¿Cuál es el lenguaje que se ejecuta en el navegador?", + ["Python", "C++", "JavaScript", "Java"], + 3 +) + +pregunta.mostrar() +respuesta_usuario = int(input("Elige la opción correcta (1-4): ")) + +if pregunta.verificar(respuesta_usuario): + print(" ¡Respuesta correcta!") +else: + print(" Respuesta incorrecta.") + +# Impresión clase Computadora +print("\n Objeto Computadora:") +mi_pc = Computadora("Lenovo", "Windows 11", 16, 512) +mi_pc.mostrar_info() +mi_pc.encender() +mi_pc.apagar() \ No newline at end of file diff --git a/clase2/valeria_ramos.py b/clase2/valeria_ramos.py new file mode 100644 index 0000000..754232f --- /dev/null +++ b/clase2/valeria_ramos.py @@ -0,0 +1,112 @@ + +# # Objeto Televisión +# """ +# Estudiante: +# - edad +# - año +# - nota +# Metodos: +# - información +# - aprobar +# """ + +#EJERCICIO 1 OBJETOS +# ¿Qué es un objeto? +# Un objeto es como una cosa o persona en la vida real, pero en programación. Tiene datos que lo describen y cosas que puede hacer. + +# ¿Qué hace el objeto Estudiante? +# Este objeto representa a un estudiante, con su nombre, edad, nota y curso. Además, puede mostrar su información y decir si aprobó o no. + +# ¿Por qué elegí Estudiante? +# Porque es fácil de entender y es algo que todos conocemos. Así puedo practicar cómo guardar información y usarla para hacer cosas, como decir si el estudiante pasó la materia. + +class Estudiante: + def __init__(self, nombre, edad, nota, curso): + self.nombre = nombre + self.edad = edad + self.nota = nota + self.curso = curso + + def informacion (self): + print (f"Nombre:{nombre}") + print (f"Edad:{edad}") + print (f"Nota:{nota}") + print (f"curso:{curso}") + + def aprobar (self): + if self.nota>=7: + print(f"{self.nombre} Felicidades! aprobaste.") + else: + print(f"{self.nombre} No aprobaste." ) + +#se pide los datos +nombre = input ("Ingresa tu nombre:") +edad = int ( input ("Ingresa tu edad:")) +nota = float(input("Ingresa tu nota:")) +curso = input("Ingrea tu curso:") + + +#creación de objeto +est1 = Estudiante(nombre, edad, nota, curso) + +#uso de métodos +est1.informacion() +est1.aprobar() + +# Ejercicio2: LISTAS Y DICCIONARIOS +#lista +pelis_fav = ["voces inocentes", "crepusculo", "Yo antes de ti"] + +print(f"Mi pelis favoritas son: {pelis_fav}") + +#dicionario + +peliculas = [ + {"nombre": "Voces Inocentes","genero": "Drama", "año": 2004 }, + {"nombre":"Crepúsculo", "genero": "Fantasía", "año": 2000}, + {"nombre": "Yo antes de ti", "genero":"Romance", "año":2005} +] + +for peli in peliculas: + print("Nombre:", peli["nombre"]) + print("Género:", peli["genero"]) + print("Año:", peli["año"]) + print("---") + + +#EJERCICIO 3: TRIVIA CON PPO + +class Pregunta: + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + + def mostrar(self): + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar(self, respuesta): + return respuesta == self.respuesta + + + +# Objectos de clase pregunta +p1 = Pregunta("¿Cuál es la capital de Francia?", ["Madrid", "París", "Londres"], 2) +p2 = Pregunta("¿Qué planeta es conocido como el Planeta Rojo?", ["Venus", "Marte", "Júpiter"], 2) +p3 = Pregunta("¿Cuántos continentes hay en el mundo?", ["5", "6", "7", "8"], 3) + +# Los ponemos en una lista +lista_preguntas = [p1, p2, p3] + +# Recorremos la lista para jugar la trivia +for pregunta in lista_preguntas: + pregunta.mostrar() + respuesta = int(input("Escribe el número de la opción correcta: ")) + if pregunta.verificar(respuesta): + print("¡Correcto!\n") + else: + print(f"Incorrecto. La respuesta correcta era la opción {pregunta.respuesta}\n") + \ No newline at end of file diff --git "a/clase2/walter_nu\303\261ez.py" "b/clase2/walter_nu\303\261ez.py" new file mode 100644 index 0000000..f2c7171 --- /dev/null +++ "b/clase2/walter_nu\303\261ez.py" @@ -0,0 +1,102 @@ +# 📱 Ejercicio 1: Objetos +class Celular: + """ + Clase Celular: + - Atributos: + - marca + - modelo + - año + - color + - Métodos: + - llamar() + - enviar_mensaje() + """ + def __init__(self, marca, modelo, año, color): + self.marca = marca + self.modelo = modelo + self.año = año + self.color = color + + def llamar(self, numero): + print(f"Llamando al número {numero} desde un {self.marca} {self.modelo}...") + + def enviar_mensaje(self, numero, mensaje): + print(f"Enviando mensaje a {numero}: '{mensaje}'") + +def ejercicio_1(): + mi_celular = Celular("Samsung", "Galaxy S22", 2022, "Negro") + mi_celular.llamar("0999999999") + mi_celular.enviar_mensaje("0999999999", "Hola, ¿cómo estás?") + print("Este objeto representa un celular moderno con métodos para llamar y enviar mensajes.") + + +# 🎬 Ejercicio 2: Listas y Diccionarios +def ejercicio_2(): + peliculas = ["Inception", "Interestelar", "Matrix"] + persona = { + "nombre": "Walter", + "genero": "Masculino", + "año": 2025 + } + + print("Mis películas favoritas son:") + for pelicula in peliculas: + print("-", pelicula) + + print("\nDatos personales:") + for clave, valor in persona.items(): + print(f"{clave.capitalize()}: {valor}") + + +# ❓ Ejercicio 3: Trivia con POO +class Pregunta: + def __init__(self, enunciado, opciones, respuesta): + self.enunciado = enunciado + self.opciones = opciones + self.respuesta = respuesta + + def mostrar(self): + print("\n🧠 Pregunta:") + print(self.enunciado) + for i, opcion in enumerate(self.opciones, 1): + print(f"{i}. {opcion}") + + def verificar_respuesta(self, eleccion_usuario): + if self.opciones[eleccion_usuario - 1].lower() == self.respuesta.lower(): + print("✅ ¡Respuesta correcta!") + else: + print(f"❌ Respuesta incorrecta. La correcta era: {self.respuesta}") + +def ejercicio_3(): + pregunta = Pregunta( + "¿Cuál es el lenguaje de programación más popular en 2025?", + ["Python", "Java", "C++", "JavaScript"], + "Python" + ) + pregunta.mostrar() + try: + eleccion = int(input("Elige una opción (1-4): ")) + if 1 <= eleccion <= 4: + pregunta.verificar_respuesta(eleccion) + else: + print("Opción fuera de rango.") + except ValueError: + print("Entrada no válida. Debe ser un número.") + + +# Menú principal +if __name__ == "__main__": + print("\n📋 MENÚ DE EJERCICIOS") + print("1. Ejercicio de Objeto (Celular)") + print("2. Ejercicio de Listas y Diccionarios") + print("3. Ejercicio de Trivia con POO") + opcion = input("Elige una opción (1-3): ") + + if opcion == "1": + ejercicio_1() + elif opcion == "2": + ejercicio_2() + elif opcion == "3": + ejercicio_3() + else: + print(" Opción inválida.") diff --git a/clase3/Andrea_yanez/joke/andrea_yanez2.py b/clase3/Andrea_yanez/joke/andrea_yanez2.py new file mode 100644 index 0000000..998138c --- /dev/null +++ b/clase3/Andrea_yanez/joke/andrea_yanez2.py @@ -0,0 +1,64 @@ +import requests + +def traducir_mymemory(texto, origen='en', destino='es'): + url = 'https://api.mymemory.translated.net/get' + params = { + 'q': texto, + 'langpair': f'{origen}|{destino}' + } + try: + response = requests.get(url, params=params) + if response.status_code == 200: + data = response.json() + return data['responseData']['translatedText'] + else: + print('❌ Error al traducir (API MyMemory).') + return texto + except requests.RequestException as e: + print(f'⚠️ Error de conexión al traducir: {e}') + return texto + +def chiste(): + try: + response = requests.get('https://official-joke-api.appspot.com/random_joke') + if response.status_code == 200: + data = response.json() + setup_en = data['setup'] + punchline_en = data['punchline'] + setup_es = traducir_mymemory(setup_en) + punchline_es = traducir_mymemory(punchline_en) + return setup_es, punchline_es + else: + print('❌ No se pudo obtener un chiste (Error en la API).') + return None, None + except requests.RequestException as e: + print(f'⚠️ Error de conexión: {e}') + return None, None + +def pedir_entrada(prompt): + entrada = input(prompt) + return entrada.strip().lower() + +def main(): + print('🤣 Presiona ENTER para ver un chiste o escribe SALIR para terminar.\n') + + entrada = pedir_entrada('') + if entrada == 'salir': + print('\n💥 ¡El programa terminó… pero el humor sigue disponible!\n') + return + + while True: + setup, punchline = chiste() + if setup and punchline: + print(f'\n🗯️ {setup}') + print(f'😂 {punchline}\n') + else: + print('😅 Intenté traer un chiste, pero se fue corriendo del susto xd.') + + entrada = pedir_entrada('¿Quieres OTRO chiste? (ENTER para sí / SALIR para no): ') + if entrada == 'salir': + print('\n💥 ¡El programa terminó… pero el humor sigue disponible!\n') + break + +if __name__ == "__main__": + main() diff --git a/clase3/Andrea_yanez/poke/andrea_yanez.py b/clase3/Andrea_yanez/poke/andrea_yanez.py new file mode 100644 index 0000000..69ea024 --- /dev/null +++ b/clase3/Andrea_yanez/poke/andrea_yanez.py @@ -0,0 +1,128 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +@app.route('/') +def index(): + # Diccionario para traducir los stats al español + stats_traduccion = { + "hp": "PS", + "attack": "Ataque", + "defense": "Defensa", + "special-attack": "Ataque Especial", + "special-defense": "Defensa Especial", + "speed": "Velocidad" + } + + search_query = request.args.get('search', '').lower() + page = int(request.args.get('page', 1)) + POKEMONS_PER_PAGE = 9 + offset = (page - 1) * POKEMONS_PER_PAGE + 20 + + pokemons = [] + + if search_query: + url = f'https://pokeapi.co/api/v2/pokemon/{search_query}' + response = requests.get(url) + if response.status_code == 200: + info_poke = response.json() + + species_url = info_poke['species']['url'] + species_response = requests.get(species_url) + if species_response.status_code == 200: + species_info = species_response.json() + gender_rate = species_info.get('gender_rate', -1) + if gender_rate == -1: + gender = "Desconocido" + elif gender_rate == 0: + gender = "Solo macho" + elif gender_rate == 8: + gender = "Solo hembra" + else: + gender = f"Macho {100 - gender_rate * 12.5}%, Hembra {gender_rate * 12.5}%" + habitat = species_info['habitat']['name'] if species_info['habitat'] else "Desconocido" + color = species_info['color']['name'] if species_info['color'] else "Desconocido" + else: + gender = "Desconocido" + habitat = "Desconocido" + color = "Desconocido" + + # Traducir los stats + stats_es = {stats_traduccion.get(s['stat']['name'], s['stat']['name']).capitalize(): s['base_stat'] for s in info_poke["stats"]} + + pokemons.append({ + 'name': info_poke['name'].upper(), + 'id': info_poke['id'], + 'sprite': info_poke['sprites']['front_default'], + 'image': info_poke['sprites']['other']['official-artwork']['front_shiny'], + 'types': [t['type']['name'] for t in info_poke['types']], + 'height': info_poke['height'], + 'weight': info_poke['weight'], + 'abilities': [a['ability']['name'] for a in info_poke['abilities']], + 'stats': stats_es, + 'species': info_poke["species"]["name"].capitalize(), + 'gender': gender, + 'habitat': habitat, + 'color': color + }) + total_pages = 1 + page = 1 + else: + url = f'https://pokeapi.co/api/v2/pokemon?limit={POKEMONS_PER_PAGE}&offset={offset}' + response = requests.get(url) + if response.status_code == 200: + results = response.json() + for poke in results['results']: + detail_response = requests.get(poke['url']) + if detail_response.status_code == 200: + info_poke = detail_response.json() + species_url = info_poke['species']['url'] + species_response = requests.get(species_url) + if species_response.status_code == 200: + species_info = species_response.json() + gender_rate = species_info.get('gender_rate', -1) + if gender_rate == -1: + gender = "Desconocido" + elif gender_rate == 0: + gender = "Solo macho" + elif gender_rate == 8: + gender = "Solo hembra" + else: + gender = f"Macho {100 - gender_rate * 12.5}%, Hembra {gender_rate * 12.5}%" + habitat = species_info['habitat']['name'] if species_info['habitat'] else "Desconocido" + color = species_info['color']['name'] if species_info['color'] else "Desconocido" + else: + gender = "Desconocido" + habitat = "Desconocido" + color = "Desconocido" + + stats_es = {stats_traduccion.get(s['stat']['name'], s['stat']['name']).capitalize(): s['base_stat'] for s in info_poke["stats"]} + + pokemons.append({ + 'name': info_poke['name'].upper(), + 'id': info_poke['id'], + 'sprite': info_poke['sprites']['front_default'], + 'image': info_poke['sprites']['other']['official-artwork']['front_shiny'], + 'types': [t['type']['name'] for t in info_poke['types']], + 'height': info_poke['height'], + 'weight': info_poke['weight'], + 'abilities': [a['ability']['name'] for a in info_poke['abilities']], + 'stats': stats_es, + 'species': info_poke["species"]["name"].capitalize(), + 'gender': gender, + 'habitat': habitat, + 'color': color + }) + total = 100 + total_pages = math.ceil((total - 20) / POKEMONS_PER_PAGE) + + return render_template('index.html', + pokemon_list=pokemons, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == '__main__': + app.run(debug=True, host='127.0.0.1', port=5000) \ No newline at end of file diff --git a/clase3/Andrea_yanez/poke/templates/index.html b/clase3/Andrea_yanez/poke/templates/index.html new file mode 100644 index 0000000..fcc1815 --- /dev/null +++ b/clase3/Andrea_yanez/poke/templates/index.html @@ -0,0 +1,80 @@ + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ + + + +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+ {{ pokemon.name }} +
+
{{ pokemon.name }} (ID: {{ pokemon.id }})
+

+ Tipo(s): {{ pokemon.types | join(', ') }}
+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }}
+ Especie: {{ pokemon.species }}
+ Género: {{ pokemon.gender }}
+ Hábitat: {{ pokemon.habitat }}
+ Color: {{ pokemon.color }}
+ Stats: +

    + {% for stat, value in pokemon.stats.items() %} +
  • {{ stat }}: {{ value }}
  • + {% endfor %} +
+

+
+
+
+ {% endfor %} +
+ + {% if pokemon_list and pokemon_list|length == 1 %} + + {% endif %} + + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + diff --git a/clase3/Lizeth_Albacura/Chisteapi/Chiste.py b/clase3/Lizeth_Albacura/Chisteapi/Chiste.py new file mode 100644 index 0000000..51c3244 --- /dev/null +++ b/clase3/Lizeth_Albacura/Chisteapi/Chiste.py @@ -0,0 +1,22 @@ +from flask import Flask, render_template +import requests + +app = Flask(__name__) + +def obtener_chiste(): + url = "https://official-joke-api.appspot.com/jokes/random" + try: + response = requests.get(url) + response.raise_for_status() + data = response.json() + return data.get("setup"), data.get("punchline") + except requests.RequestException: + return "Error al obtener el chiste.", "" + +@app.route("/") +def index(): + setup, punchline = obtener_chiste() + return render_template("index.html", setup=setup, punchline=punchline) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clase3/Lizeth_Albacura/Chisteapi/templates/index.html b/clase3/Lizeth_Albacura/Chisteapi/templates/index.html new file mode 100644 index 0000000..e578b36 --- /dev/null +++ b/clase3/Lizeth_Albacura/Chisteapi/templates/index.html @@ -0,0 +1,36 @@ + + + + + Chiste del Día + + + +
+

😂 Chiste para alegrarte el día

+

{{ setup }}

+

{{ punchline }}

+
+ 🔄 Siguiente chiste +
+ + \ No newline at end of file diff --git a/clase3/Lizeth_Albacura/Pokeapi.py b/clase3/Lizeth_Albacura/Pokeapi.py new file mode 100644 index 0000000..724706d --- /dev/null +++ b/clase3/Lizeth_Albacura/Pokeapi.py @@ -0,0 +1,65 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +POKEMONS_PER_PAGE = 9 + +@app.route('/', methods=['GET']) +def index(): + search_query = request.args.get('search', '').lower() + page = int(request.args.get('page', 1)) + + offset = (page - 1) * POKEMONS_PER_PAGE + url = f'https://pokeapi.co/api/v2/pokemon?limit={POKEMONS_PER_PAGE}&offset={offset}' + response = requests.get(url) + + if response.status_code != 200: + return "Error al obtener los Pokémon" + + results = response.json() + all_pokemon = [] + + for poke in results['results']: + poke_data = requests.get(poke['url']).json() + name = poke_data['name'] + + # Aplica el filtro de búsqueda si hay un término, y lo incluye si coincide + if search_query and search_query not in name: + continue + + held_items = [item['item']['name'] for item in poke_data['held_items']] if poke_data['held_items'] else ['None'] + + pokemon = { + 'name': name.upper(), + 'front_sprite': poke_data['sprites']['front_default'], + 'back_sprite': poke_data['sprites']['back_default'], + 'front_image': poke_data['sprites']['other']['official-artwork']['front_default'], + 'back_image': poke_data['sprites']['other']['official-artwork'].get('back_default', None), + 'height': poke_data['height'], + 'weight': poke_data['weight'], + 'species': poke_data['species']['name'].capitalize(), + 'types': [t['type']['name'].capitalize() for t in poke_data['types']], + 'is_default': poke_data['is_default'], + 'moves': [move['move']['name'] for move in poke_data['moves']] if poke_data['moves'] else ['None'], + 'abilities': [a['ability']['name'] for a in poke_data['abilities']], + 'base_experience': poke_data['base_experience'], + 'order': poke_data['order'], + 'held_items': held_items, + 'stats': {s['stat']['name']: s['base_stat'] for s in poke_data['stats']}, + } + + all_pokemon.append(pokemon) + + total = 100 + total_pages = math.ceil(total / POKEMONS_PER_PAGE) + + return render_template('index.html', + pokemon_list=all_pokemon, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/clase3/Lizeth_Albacura/Pokeapi/Pokeapi.py b/clase3/Lizeth_Albacura/Pokeapi/Pokeapi.py new file mode 100644 index 0000000..7c6e09f --- /dev/null +++ b/clase3/Lizeth_Albacura/Pokeapi/Pokeapi.py @@ -0,0 +1,61 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +POKEMONS_PER_PAGE = 9 + +@app.route('/', methods=['GET']) +def index(): + search_query = request.args.get('search', '').lower() + page = int(request.args.get('page', 1)) + + offset = (page - 1) * POKEMONS_PER_PAGE + url = f'https://pokeapi.co/api/v2/pokemon?limit={POKEMONS_PER_PAGE}&offset={offset}' + response = requests.get(url) + + if response.status_code != 200: + return "Error al obtener los Pokémon" + + results = response.json() + all_pokemon = [] + + for poke in results['results']: + poke_data = requests.get(poke['url']).json() + name = poke_data['name'] + + if search_query in name: + held_items = [item['item']['name'] for item in poke_data['held_items']] if poke_data['held_items'] else ['None'] + species_name = poke_data['species']['name'] if 'species' in poke_data else 'Unknown' + + pokemon = { + 'name': name.upper(), + 'front_sprite': poke_data['sprites']['front_default'], + 'back_sprite': poke_data['sprites']['back_default'], + 'front_image': poke_data['sprites']['other']['official-artwork']['front_default'], + 'back_image': poke_data['sprites']['other']['official-artwork'].get('back_default', None), + 'height': poke_data['height'], + 'weight': poke_data['weight'], + 'moves': [move['move']['name'] for move in poke_data['moves']] if poke_data['moves'] else ['None'], + 'abilities': [a['ability']['name'] for a in poke_data['abilities']], + 'base_experience': poke_data['base_experience'], + 'order': poke_data['order'], + 'held_items': held_items, + 'types': [t['type']['name'] for t in poke_data['types']], + 'stats': {s['stat']['name']: s['base_stat'] for s in poke_data['stats']}, + 'species': species_name + } + all_pokemon.append(pokemon) + + total = 100 + total_pages = math.ceil(total / POKEMONS_PER_PAGE) + + return render_template('index.html', + pokemon_list=all_pokemon, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/Lizeth_Albacura/Pokeapi/templates/index.html b/clase3/Lizeth_Albacura/Pokeapi/templates/index.html new file mode 100644 index 0000000..6a851e3 --- /dev/null +++ b/clase3/Lizeth_Albacura/Pokeapi/templates/index.html @@ -0,0 +1,96 @@ + + + + + Pokédex + + + + +
+

Pokédex

+ +
+ + +
+ +
+ {% for pokemon in pokemon_list %} +
+
+
+
{{ pokemon.name }}
+ + {% if pokemon.front_sprite %} + Frente + {% endif %} + {% if pokemon.back_sprite %} + Espalda + {% endif %} +
+ {% if pokemon.front_image %} + Arte frontal + {% endif %} + {% if pokemon.back_image %} + Arte trasero + {% endif %} + +
    +
  • Altura: {{ pokemon.height }}
  • +
  • Peso: {{ pokemon.weight }}
  • +
  • Especie: {{ pokemon.species }}

    +
  • Tipos: {{ pokemon.types | join(', ') }}

    +
  • + Forma estándar: {{ 'Sí' if pokemon.is_default else 'No' }} +
  • Experiencia Base: {{ pokemon.base_experience }}
  • +
  • Orden:{{ pokemon.order}}
  • +
  • Habilidades: {{ pokemon.abilities | join(', ') }}
  • +
  • Ítems: {{ pokemon.held_items | join(', ') }}
  • +
  • Movimientos: {{ pokemon.moves[:5] | join(', ') }}{% if pokemon.moves|length > 5 %}, ...{% endif %}
  • + +
  • + Stats: +
      + {% for stat, value in pokemon.stats.items() %} +
    • {{ stat }}: {{ value }}
    • + {% endfor %} +
    +
  • +
+
+
+
+ {% endfor %} +
+ +
+ {% if page > 1 %} + ← Anterior + {% endif %} + Página {{ page }} de {{ total_pages }} + {% if page < total_pages %} + Siguiente → + {% endif %} +
+
+ + + + \ No newline at end of file diff --git a/clase3/Lizeth_Albacura/templates/index.html b/clase3/Lizeth_Albacura/templates/index.html new file mode 100644 index 0000000..6a851e3 --- /dev/null +++ b/clase3/Lizeth_Albacura/templates/index.html @@ -0,0 +1,96 @@ + + + + + Pokédex + + + + +
+

Pokédex

+ +
+ + +
+ +
+ {% for pokemon in pokemon_list %} +
+
+
+
{{ pokemon.name }}
+ + {% if pokemon.front_sprite %} + Frente + {% endif %} + {% if pokemon.back_sprite %} + Espalda + {% endif %} +
+ {% if pokemon.front_image %} + Arte frontal + {% endif %} + {% if pokemon.back_image %} + Arte trasero + {% endif %} + +
    +
  • Altura: {{ pokemon.height }}
  • +
  • Peso: {{ pokemon.weight }}
  • +
  • Especie: {{ pokemon.species }}

    +
  • Tipos: {{ pokemon.types | join(', ') }}

    +
  • + Forma estándar: {{ 'Sí' if pokemon.is_default else 'No' }} +
  • Experiencia Base: {{ pokemon.base_experience }}
  • +
  • Orden:{{ pokemon.order}}
  • +
  • Habilidades: {{ pokemon.abilities | join(', ') }}
  • +
  • Ítems: {{ pokemon.held_items | join(', ') }}
  • +
  • Movimientos: {{ pokemon.moves[:5] | join(', ') }}{% if pokemon.moves|length > 5 %}, ...{% endif %}
  • + +
  • + Stats: +
      + {% for stat, value in pokemon.stats.items() %} +
    • {{ stat }}: {{ value }}
    • + {% endfor %} +
    +
  • +
+
+
+
+ {% endfor %} +
+ +
+ {% if page > 1 %} + ← Anterior + {% endif %} + Página {{ page }} de {{ total_pages }} + {% if page < total_pages %} + Siguiente → + {% endif %} +
+
+ + + + \ No newline at end of file diff --git a/clase3/Telebot walter/walter_nunez.py b/clase3/Telebot walter/walter_nunez.py new file mode 100644 index 0000000..da18c50 --- /dev/null +++ b/clase3/Telebot walter/walter_nunez.py @@ -0,0 +1,44 @@ +import telebot + +# Reemplaza este token con el tuyo +TOKEN_BOT = '7597701644:AAGIdJVqk7KoelPcvRXU2TupDEF6kUakYRo' + +# Crea una instancia del bot +bot = telebot.TeleBot(TOKEN_BOT) + +# Comando /start +@bot.message_handler(commands=['start']) +def send_welcome(message): + bot.send_message(message.chat.id, "¡Hola! Bienvenido, escribe 'paquetes' para ver los servicios disponibles.") + +# Si el usuario escribe 'paquetes', se muestran las opciones +@bot.message_handler(func=lambda m: m.text.lower() == "paquetes") +def mostrar_paquetes(message): + opciones_texto = ( + "Estos son los paquetes que tenemos:\n" + "1. Manicure\n" + "2. Corte de cabello\n" + "3. Pedicure\n" + "Escribe el número del paquete que deseas:" + ) + bot.send_message(message.chat.id, opciones_texto) + bot.register_next_step_handler(message, procesar_opcion) + +# Procesar respuesta del usuario +def procesar_opcion(message): + seleccion = message.text.strip() + if seleccion == "1": + respuesta = "Has seleccionado: Manicure 💅" + elif seleccion == "2": + respuesta = "Has seleccionado: Corte de cabello 💇" + elif seleccion == "3": + respuesta = "Has seleccionado: Pedicure 🦶" + else: + respuesta = "Opción no válida. Por favor escribe 1, 2 o 3." + + bot.send_message(message.chat.id, respuesta) + +# Ejecutar el bot +if __name__ == '__main__': + print("Está ejecutándose el bot...") + bot.infinity_polling() diff --git a/clase3/Wendy_Moreno.py b/clase3/Wendy_Moreno.py new file mode 100644 index 0000000..ac85296 --- /dev/null +++ b/clase3/Wendy_Moreno.py @@ -0,0 +1 @@ +#Realizado los 2 ejercicios uno de pokemon que tiene nombre flask_pokeapi y el otro flask_chistes \ No newline at end of file diff --git a/clase3/api2_pablo_colcha/app.py b/clase3/api2_pablo_colcha/app.py new file mode 100644 index 0000000..5afd3a6 --- /dev/null +++ b/clase3/api2_pablo_colcha/app.py @@ -0,0 +1,51 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +MORTI_PER_PAGE = 9 + +@app.route('/', methods=['GET']) +def index(): + search_query = request.args.get('search', '').lower() + page = int(request.args.get('page', 1)) + + url = f'https://rickandmortyapi.com/api/character/?page={page}' + response = requests.get(url) + + if response.status_code != 200: + return "Error al obtener los personajes." + + data = response.json() + all_characters = [] + + for character in data['results']: + name = character['name'].lower() + + if search_query in name: + morti = { + 'id': character['id'], + 'name': character['name'], + 'status': character['status'], + 'species': character['species'], + 'type': character['type'] if character['type'] else 'Unknown', + 'gender': character['gender'], + 'origin': character['origin']['name'], + 'location': character['location']['name'], + 'image': character['image'], + 'episode_count': len(character['episode']) + } + all_characters.append(morti) + + total = data['info']['count'] + total_pages = data['info']['pages'] + + return render_template('index.html', + character_list=all_characters, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/api2_pablo_colcha/templates/index.html b/clase3/api2_pablo_colcha/templates/index.html new file mode 100644 index 0000000..22fc711 --- /dev/null +++ b/clase3/api2_pablo_colcha/templates/index.html @@ -0,0 +1,58 @@ + + + + + + Rick and Morty Characters + + + +
+

Rick and Morty Characters

+ +
+
+ + +
+
+ + {% if character_list %} +
+ {% for character in character_list %} +
+
+ {{ character.name }} +
+
{{ character.name }}
+

+ Estado: {{ character.status }}
+ Especie: {{ character.species }}
+ Género: {{ character.gender }}
+ Origen: {{ character.origin }}
+ Ubicación: {{ character.location }}
+ Episodios: {{ character.episodes }} +

+
+
+
+ {% endfor %} +
+ + + + + {% else %} +

No se encontraron personajes.

+ {% endif %} +
+ + diff --git a/clase3/carlos_bodero/chiste/app.py b/clase3/carlos_bodero/chiste/app.py new file mode 100644 index 0000000..63c6ed1 --- /dev/null +++ b/clase3/carlos_bodero/chiste/app.py @@ -0,0 +1,23 @@ +from flask import Flask, render_template,jsonify +import requests + +app = Flask(__name__) + +@app.route("/") +def index(): + return render_template("index.html") + +@app.route("/joke") +def joke(): + response = requests.get("https://official-joke-api.appspot.com/jokes/random") + if response.status_code == 200: + data = response.json() + chiste = f"{data['setup']} {data['punchline']}" + else: + chiste = "No hay chiste" + + return jsonify({"joke":chiste}) + + +if __name__ == "__main__": + app.run(debug=True) \ No newline at end of file diff --git a/clase3/carlos_bodero/chiste/templates/index.html b/clase3/carlos_bodero/chiste/templates/index.html new file mode 100644 index 0000000..3b2b8fc --- /dev/null +++ b/clase3/carlos_bodero/chiste/templates/index.html @@ -0,0 +1,21 @@ + + + + + Chistes Flask + + + +

Bienvenido

+ +
+ +
+ + diff --git a/clase3/carlos_bodero/pokemon/app.py b/clase3/carlos_bodero/pokemon/app.py new file mode 100644 index 0000000..3d37d33 --- /dev/null +++ b/clase3/carlos_bodero/pokemon/app.py @@ -0,0 +1,38 @@ +#api pokemon +import random +import requests +from flask import Flask, render_template, request + +app = Flask(__name__) + +POKEAPI_URL = "https://pokeapi.co/api/v2/pokemon/" + +def get_pokemon_data(poke_id): + res = requests.get(f"{POKEAPI_URL}{poke_id}") + if res.status_code != 200: + return None + data = res.json() + return { + "id": data["id"], + "name": data["name"].capitalize(), + "image": data["sprites"]["front_default"], + "height": data["height"], + "weight": data["weight"], + "types": ", ".join(t["type"]["name"] for t in data["types"]), + "base_experience": data["base_experience"], + "abilities": ", ".join(a["ability"]["name"] for a in data["abilities"]), + "hp": data["stats"][0]["base_stat"], + "attack": data["stats"][1]["base_stat"], + "defense": data["stats"][2]["base_stat"], + } + +@app.route("/", methods=["GET", "POST"]) +def index(): + pokemons = [] + if request.method == "POST": + ids = random.sample(range(1, 151), 9) + pokemons = [get_pokemon_data(poke_id) for poke_id in ids if get_pokemon_data(poke_id)] + return render_template("index.html", pokemons=pokemons) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clase3/carlos_bodero/pokemon/static/styles.css b/clase3/carlos_bodero/pokemon/static/styles.css new file mode 100644 index 0000000..b16b95a --- /dev/null +++ b/clase3/carlos_bodero/pokemon/static/styles.css @@ -0,0 +1,40 @@ +body { + font-family: Arial, sans-serif; + text-align: center; + background-color: #f1f1f1; +} + +h1 { + margin-top: 20px; + color: #e60026; +} + +form { + margin: 20px; +} + +.grid { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 20px; +} + +.card { + background-color: white; + border-radius: 10px; + box-shadow: 0 0 8px rgba(0,0,0,0.2); + padding: 15px; + width: 250px; +} + +.card img { + width: 120px; + height: 120px; +} + +ul { + list-style-type: none; + padding: 0; + text-align: left; +} diff --git a/clase3/carlos_bodero/pokemon/templates/index.html b/clase3/carlos_bodero/pokemon/templates/index.html new file mode 100644 index 0000000..24d11b6 --- /dev/null +++ b/clase3/carlos_bodero/pokemon/templates/index.html @@ -0,0 +1,34 @@ + + + + + Pokedesk + + + +

Pokedesk

+
+ +
+ +
+ {% for p in pokemons %} +
+ {{ p.name }} +

{{ p.name }}

+
    +
  • ID: {{ p.id }}
  • +
  • Tipo: {{ p.types }}
  • +
  • Altura: {{ p.height }}
  • +
  • Peso: {{ p.weight }}
  • +
  • Experiencia: {{ p.base_experience }}
  • +
  • Habilidad(es): {{ p.abilities }}
  • +
  • HP: {{ p.hp }}
  • +
  • Ataque: {{ p.attack }}
  • +
  • Defensa: {{ p.defense }}
  • +
+
+ {% endfor %} +
+ + diff --git a/clase3/clase3.py b/clase3/clase3.py new file mode 100644 index 0000000..987f89a --- /dev/null +++ b/clase3/clase3.py @@ -0,0 +1,12 @@ +import requests + +data = requests.get('https://fakestoreapi.com/products').json() +print(data[0]) + +for prod in data: + print(f"{prod['title']} - ${prod['price']}") + +for prod in data: + if prod['category'] == 'electronics': + print(f"{prod['title']} - ${prod['price']}") + diff --git a/clase3/flask_chistes/app.py b/clase3/flask_chistes/app.py new file mode 100644 index 0000000..e81e3a6 --- /dev/null +++ b/clase3/flask_chistes/app.py @@ -0,0 +1,27 @@ +import requests +from flask import Flask, render_template + +app = Flask(__name__) + +@app.route('/') +def chiste(): + chiste = {} + error = None + + try: + response = requests.get("https://official-joke-api.appspot.com/jokes/random") + if response.status_code == 200: + chiste = response.json() + else: + error = "No se pudo obtener un chiste. Intenta de nuevo." + except Exception as e: + error = f"Error al conectarse a la API: {e}" + + return render_template("index.html", chiste=chiste, error=error) + +@app.route('/salir') +def salir(): + return "

👋 ¡Gracias por reír con nosotros! Hasta la próxima.

" + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/flask_chistes/erika_torres.py b/clase3/flask_chistes/erika_torres.py new file mode 100644 index 0000000..20c0fe7 --- /dev/null +++ b/clase3/flask_chistes/erika_torres.py @@ -0,0 +1,61 @@ +import requests + +URL = "https://fakestoreapi.com" + +def deserialize_json(json_data): + """ + Deserialize JSON data into a Python object. + """ + try: + return json_data.json() + except ValueError as e: + print(f"Error deserializing JSON: {e}") + return None + +def serialize_json(data): + """ + Serialize a Python object into JSON format. + """ + try: + return json.dumps(data, indent=2) + except TypeError as e: + print(f"Error serializing to JSON: {e}") + return None + +def get_products(): + url = f"{URL}/products" + response = requests.get(url) + if response.status_code == 200: + return response.json() + else: + return None + +def get_product_by_id(product_id): + url = f"{URL}/products/{product_id}" + response = requests.get(url) + if response.status_code == 200: + return response.json() + else: + return None + +if __name__ == "__main__": + products = get_products() + for product in products: + print(f"Product ID: {product['id']}") + print(f"Title: {product['title']}") + print(f"Price: {product['price']}") + print(f"Description: {product['description']}") + print(f"Imagen: {product['image']}") + print("-" * 20) + + product = get_product_by_id(15) + print(f"Product ID: {product['id']}") + print(f"Title: {product['title']}") + print(f"Price: {product['price']}") + print(f"Description: {product['description']}") + print(f"Imagen: {product['image']}") + print("-" * 20) + + objserialize = serialize_json(products) + print(f"Serialized JSON: {objserialize}") + \ No newline at end of file diff --git a/clase3/flask_chistes/templates/index.html b/clase3/flask_chistes/templates/index.html new file mode 100644 index 0000000..ae97246 --- /dev/null +++ b/clase3/flask_chistes/templates/index.html @@ -0,0 +1,64 @@ + + + + + + 😂 Chiste del Día + + + + + + + + + + + +
+
+
+
+
😂
+

Chiste del Día

+ + {% if error %} +
{{ error }}
+ {% else %} +

{{ chiste.setup }}

+

{{ chiste.punchline }}

+ {% endif %} + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/clase3/flask_pokeapi/app.py b/clase3/flask_pokeapi/app.py new file mode 100644 index 0000000..94dbb0f --- /dev/null +++ b/clase3/flask_pokeapi/app.py @@ -0,0 +1,54 @@ +import math + +import requests +from flask import Flask, render_template, request + +app = Flask(__name__) + +@app.route('/') +def index(): + page = int(request.args.get('page', 1)) + search = request.args.get('search', '').lower() + per_page = 9 + total_pokemons = 100 + offset = (page - 1) * per_page + pokemons = [] + + if search: + data = get_pokemon(search) + if data: + pokemons.append(data) + total_pages = 1 + else: + url = f'https://pokeapi.co/api/v2/pokemon?offset={offset}&limit={per_page}' + response = requests.get(url) + results = response.json().get('results', []) + for item in results: + poke_data = get_pokemon(item['name']) + if poke_data: + pokemons.append(poke_data) + total_pages = math.ceil(total_pokemons / per_page) + + return render_template('index.html', + pokemon_list=pokemons, + search_query=search, + page=page, + total_pages=total_pages) + +def get_pokemon(name): + url = f'https://pokeapi.co/api/v2/pokemon/{name}' + response = requests.get(url) + if response.status_code == 200: + data = response.json() + return { + 'name': data['name'].capitalize(), + 'image_front': data['sprites']['front_default'], + 'image_back': data['sprites']['back_default'], + 'height': data['height'], + 'weight': data['weight'], + 'abilities': [a['ability']['name'] for a in data['abilities']] + } + return None + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/flask_pokeapi/templates/index.html b/clase3/flask_pokeapi/templates/index.html new file mode 100644 index 0000000..a9d1ea8 --- /dev/null +++ b/clase3/flask_pokeapi/templates/index.html @@ -0,0 +1,59 @@ + + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+
+ Frente + Atrás +
+
+
{{ pokemon.name }}
+

+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }} +

+
+
+
+ {% endfor %} +
+ + + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + diff --git a/clase3/geomara_tambaco/geomara_tambaco.py b/clase3/geomara_tambaco/geomara_tambaco.py new file mode 100644 index 0000000..05a42b9 --- /dev/null +++ b/clase3/geomara_tambaco/geomara_tambaco.py @@ -0,0 +1,81 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +def obtener_pokemon(nombre_o_url): + try: + if nombre_o_url.startswith("http"): + url = nombre_o_url + else: + url = f"https://pokeapi.co/api/v2/pokemon/{nombre_o_url.lower()}" + + r = requests.get(url) + r.raise_for_status() + data = r.json() + + return { + "name": data["name"].capitalize(), + "image": data["sprites"]["front_default"], + "types": [t["type"]["name"] for t in data["types"]], + "height": data["height"], + "weight": data["weight"], + "abilities": [a["ability"]["name"] for a in data["abilities"]], + } + + except Exception as e: + return None + +@app.route("/") +def index(): + search_query = request.args.get("search", "").strip().lower() + try: + page = int(request.args.get("page", 1)) + except ValueError: + page = 1 # si viene algo no numérico, default a 1 + + limit = 9 + offset = (page - 1) * limit + + pokemon_list = [] + total_count = 0 + + if search_query: + pokemon = obtener_pokemon(search_query) + if pokemon: + pokemon_list = [pokemon] + total_count = 1 + else: + pokemon_list = [] + else: + try: + url = f"https://pokeapi.co/api/v2/pokemon?offset={offset}&limit={limit}" + res = requests.get(url) + res.raise_for_status() + data = res.json() + + total_count = data["count"] + for item in data["results"]: + p = obtener_pokemon(item["url"]) + if p: + pokemon_list.append(p) + except Exception as e: + pokemon_list = [] + + total_pages = math.ceil(total_count / limit) if not search_query else 1 + + # Validar que page esté entre 1 y total_pages + if page < 1: + page = 1 + elif page > total_pages: + page = total_pages if total_pages > 0 else 1 + + return render_template("index.html", + pokemon_list=pokemon_list, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clase3/geomara_tambaco/geomara_tambaco2.py b/clase3/geomara_tambaco/geomara_tambaco2.py new file mode 100644 index 0000000..ea1cae7 --- /dev/null +++ b/clase3/geomara_tambaco/geomara_tambaco2.py @@ -0,0 +1,28 @@ +import requests + +def obtener_chiste(): + try: + respuesta = requests.get("https://official-joke-api.appspot.com/jokes/random") + respuesta.raise_for_status() + chiste = respuesta.json() + return chiste + except Exception as e: + print(f"Error al obtener chiste: {e}") + return None + +def main(): + print("Presiona Enter para obtener un chiste o escribe 'salir' para terminar.") + while True: + entrada = input("> ").strip().lower() + if entrada == "salir": + print("¡Hasta luego!") + break + chiste = obtener_chiste() + if chiste: + print(f"\nSetup: {chiste['setup']}") + print(f"Punchline: {chiste['punchline']}\n") + else: + print("No se pudo obtener un chiste, intenta de nuevo.") + +if __name__ == "__main__": + main() diff --git a/clase3/geomara_tambaco/requirements.txt b/clase3/geomara_tambaco/requirements.txt new file mode 100644 index 0000000..bdff308 Binary files /dev/null and b/clase3/geomara_tambaco/requirements.txt differ diff --git a/clase3/geomara_tambaco/templates/index.html b/clase3/geomara_tambaco/templates/index.html new file mode 100644 index 0000000..68792c3 --- /dev/null +++ b/clase3/geomara_tambaco/templates/index.html @@ -0,0 +1,57 @@ + + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+ {{ pokemon.name }} +
+
{{ pokemon.name }}
+

+ Tipo: {{ pokemon.types | join(', ') }}
+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }} +

+
+
+
+ {% endfor %} +
+ + + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + diff --git a/clase3/george_penafiel/app.py b/clase3/george_penafiel/app.py new file mode 100644 index 0000000..daaca2f --- /dev/null +++ b/clase3/george_penafiel/app.py @@ -0,0 +1,58 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +POKEMONS_PER_PAGE = 9 + +@app.route('/', methods=['GET']) +def index(): + search_query = request.args.get('search', '').lower() + page = int(request.args.get('page', 1)) + + offset = (page - 1) * POKEMONS_PER_PAGE + url = f'https://pokeapi.co/api/v2/pokemon?limit={POKEMONS_PER_PAGE}&offset={offset}' + response = requests.get(url) + + if response.status_code != 200: + return "Error al obtener los Pokémon de la API." + + results = response.json() + + all_pokemon = [] + total_pokemon_count = results.get('count', 0) + + for poke in results['results']: + poke_data_response = requests.get(poke['url']) + + if poke_data_response.status_code != 200: + continue + + poke_data = poke_data_response.json() + + name = poke_data['name'] + + if search_query in name.lower(): + pokemon = { + 'id': poke_data['id'], + 'name': name.upper(), + 'sprite': poke_data['sprites']['front_default'], + 'image': poke_data['sprites']['other']['official-artwork']['front_shiny'], + 'types': [t['type']['name'] for t in poke_data['types']], + 'height': poke_data['height'], + 'weight': poke_data['weight'], + 'abilities': [a['ability']['name'] for a in poke_data['abilities']] + } + all_pokemon.append(pokemon) + + total_pages = math.ceil(total_pokemon_count / POKEMONS_PER_PAGE) + + return render_template('index.html', + pokemon_list=all_pokemon, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/clase3/george_penafiel/chistes_consola.py b/clase3/george_penafiel/chistes_consola.py new file mode 100644 index 0000000..3fb59d4 --- /dev/null +++ b/clase3/george_penafiel/chistes_consola.py @@ -0,0 +1,44 @@ +import requests + +def obtener_chiste(): + url = "https://official-joke-api.appspot.com/jokes/random" + try: + response = requests.get(url) + response.raise_for_status() + chiste_data = response.json() + + setup = chiste_data.get('setup') + punchline = chiste_data.get('punchline') + + return setup, punchline + except requests.exceptions.RequestException as e: + print(f"Error de conexión o de la API: {e}") + return None, None + except ValueError: + print("Error: La respuesta de la API no es un JSON válido.") + return None, None + +def main(): + print("¡Bienvenido al generador de chistes!") + print("Presiona ENTER para obtener un chiste nuevo, o escribe 'salir' para terminar.") + + while True: + entrada = input("\n> ").strip().lower() + + if entrada == "salir": + print("¡Hasta la próxima! Espero que te hayas reído.") + break + elif entrada == "": + setup, punchline = obtener_chiste() + if setup and punchline: + print("\n--- ¡Chiste! ---") + print(f"Setup: {setup}") + print(f"Punchline: {punchline}") + print("----------------") + else: + print("No se pudo obtener un chiste. Intenta de nuevo.") + else: + print("Comando no reconocido. Presiona ENTER para un chiste o 'salir' para terminar.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/clase3/george_penafiel/templates/index.html b/clase3/george_penafiel/templates/index.html new file mode 100644 index 0000000..33cbb24 --- /dev/null +++ b/clase3/george_penafiel/templates/index.html @@ -0,0 +1,99 @@ + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+ {{ pokemon.name }} +
+
{{ pokemon.name }}
+

+ Número en la Pokédex: {{ pokemon.id }}
+ Tipo: {{ pokemon.types | join(', ') }}
+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }} +

+
+
+
+ {% endfor %} +
+ + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + \ No newline at end of file diff --git a/clase3/jazmin_rodriguez.py b/clase3/jazmin_rodriguez.py new file mode 100644 index 0000000..a035907 --- /dev/null +++ b/clase3/jazmin_rodriguez.py @@ -0,0 +1,66 @@ +import json + +import requests + +URL = "https://fakestoreapi.com" + +def deserialize_json(json_data): + """ + Deserialize JSON data into a Python object. + """ + try: + return json_data.json() + except ValueError as e: + print(f"Error deserializing JSON: {e}") + return None + +def serialize_json(data): + """ + Serialize a Python object into JSON format. + """ + try: + return json.dumps(data, indent=2) + except TypeError as e: + print(f"Error serializing to JSON: {e}") + return None + +def get_products(): + url = f"{URL}/products" + response = requests.get(url) + if response.status_code == 200: + return response.json() + else: + return None + +def get_product_by_id(product_id): + url = f"{URL}/products/{product_id}" + response = requests.get(url) + if response.status_code == 200: + return response.json() + else: + return None + +if __name__ == "__main__": + products = get_products() + for product in products: + print(f"Product ID: {product['id']}") + print(f"Title: {product['title']}") + print(f"Price: {product['price']}") + print(f"Description: {product['description']}") + print(f"Imagen: {product['image']}") + print("-" * 20) + + product = get_product_by_id(15) + print(f"Product ID: {product['id']}") + print(f"Title: {product['title']}") + print(f"Price: {product['price']}") + print(f"Description: {product['description']}") + print(f"Imagen: {product['image']}") + print("-" * 20) + + objserialize = serialize_json(products) + print(f"Serialized JSON: {objserialize}") + + # objDeserialize = deserialize_json(response) + # print(f"Deserialized JSON: {objDeserialize}") + diff --git a/clase3/jorge_guato/app.py b/clase3/jorge_guato/app.py new file mode 100644 index 0000000..6c99a01 --- /dev/null +++ b/clase3/jorge_guato/app.py @@ -0,0 +1,101 @@ +from flask import Flask, render_template, request +import requests, random + +app = Flask(__name__) + +# 🔍 Obtener detalle de un Pokémon desde su URL +def obtener_pokemon_detalle(url): + try: + res = requests.get(url) + res.raise_for_status() + data = res.json() + return { + "ID": data['id'], + "Nombre": data['name'].capitalize(), + "Altura": data['height'], + "Peso": data['weight'], + "Experiencia base": data['base_experience'], + "Tipos": [t['type']['name'] for t in data['types']], + "Habilidades": [h['ability']['name'] for h in data['abilities']], + "Imagen": data['sprites']['front_default'], + "Orden": data['order'], + "Movimientos": [m['move']['name'] for m in data['moves'][:3]], + } + except Exception as e: + print(f"❌ Error al obtener detalles: {e}") + return None + +# 📄 Obtener 9 Pokémon por página +def obtener_pokemons_por_pagina(pagina=1, por_pagina=9): + url = f"https://pokeapi.co/api/v2/pokemon?offset={(pagina - 1) * por_pagina}&limit={por_pagina}" + try: + res = requests.get(url) + res.raise_for_status() + data = res.json() + pokemons = [] + for p in data['results']: + info = obtener_pokemon_detalle(p['url']) + if info: + pokemons.append(info) + return pokemons + except Exception as e: + print(f"❌ Error al obtener lista: {e}") + return [] + +# 🎲 Obtener 3 Pokémon aleatorios +def obtener_3_pokemons_azar(): + pokemons = [] + for pid in random.sample(range(1, 1000), 3): + info = obtener_pokemon_detalle(f"https://pokeapi.co/api/v2/pokemon/{pid}") + if info: + pokemons.append(info) + return pokemons + +# 😂 Obtener chiste desde JokeAPI +def obtener_chiste(): + try: + res = requests.get("https://v2.jokeapi.dev/joke/Any?type=twopart") + res.raise_for_status() + data = res.json() + return { + "setup": data["setup"], + "punchline": data["delivery"] + } + except: + return None + +# 🏠 Inicio y búsqueda de Pokémon +@app.route("/") +@app.route("/pokemon") +def buscar_pokemon(): + nombre = request.args.get("pokemon") + pokemon = None + if nombre: + pokemon = obtener_pokemon_detalle(f"https://pokeapi.co/api/v2/pokemon/{nombre.lower()}") + return render_template("index.html", pokemon=pokemon) + +# 🎲 3 Pokémon aleatorios +@app.route("/random") +def mostrar_aleatorios(): + pokemons = obtener_3_pokemons_azar() + return render_template("index.html", random_pokemons=pokemons) + +# 📄 Paginación de Pokémon (página 1 por defecto) +@app.route("/menu") +def menu(): + opcion = request.args.get("opcion") + if opcion == "pagina": + pokemons = obtener_pokemons_por_pagina(pagina=1) + return render_template("index.html", pokemons_pagina=pokemons) + elif opcion == "random": + return mostrar_aleatorios() + return render_template("index.html") + +# 😂 Chiste aleatorio +@app.route("/joke") +def chiste(): + joke = obtener_chiste() + return render_template("index.html", joke=joke) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clase3/jorge_guato/templates/index.html b/clase3/jorge_guato/templates/index.html new file mode 100644 index 0000000..ba5aa45 --- /dev/null +++ b/clase3/jorge_guato/templates/index.html @@ -0,0 +1,91 @@ + + + + + + + PokéAPI + Chistes + + + +
+

🔍 Explorador de Pokémon y Chistes

+ +
+
+ + +
+
+ +
+
+ + +
+ +
+ + {% if pokemon %} +
+
+
#{{ pokemon.ID }} - {{ pokemon.Nombre }}
+ Sprite +

Tipos: {{ pokemon.Tipos | join(", ") }}

+

Altura: {{ pokemon.Altura }} | Peso: {{ pokemon.Peso }}

+

Habilidades: {{ pokemon.Habilidades | join(", ") }}

+

Movimientos: {{ pokemon.Movimientos | join(", ") }}

+
+
+ {% endif %} + + {% if pokemons_pagina %} +

📄 Página de Pokémons

+
+ {% for poke in pokemons_pagina %} +
+
+
+
#{{ poke.ID }} - {{ poke.Nombre }}
+

Tipos: {{ poke.Tipos | join(", ") }}

+ {{ poke.Nombre }} +
+
+
+ {% endfor %} +
+ {% endif %} + + {% if random_pokemons %} +

🎲 Pokémon aleatorios:

+
+ {% for poke in random_pokemons %} +
+
+
+
{{ poke.Nombre }}
+

Tipos: {{ poke.Tipos | join(", ") }}

+ {{ poke.Nombre }} +
+
+
+ {% endfor %} +
+ {% endif %} + + {% if joke %} +
+

{{ joke.setup }}

+

{{ joke.punchline }}

+
+ {% endif %} + + +
+ + diff --git a/clase3/jorge_luis_castellanos/jokes/app.py b/clase3/jorge_luis_castellanos/jokes/app.py new file mode 100644 index 0000000..e81e3a6 --- /dev/null +++ b/clase3/jorge_luis_castellanos/jokes/app.py @@ -0,0 +1,27 @@ +import requests +from flask import Flask, render_template + +app = Flask(__name__) + +@app.route('/') +def chiste(): + chiste = {} + error = None + + try: + response = requests.get("https://official-joke-api.appspot.com/jokes/random") + if response.status_code == 200: + chiste = response.json() + else: + error = "No se pudo obtener un chiste. Intenta de nuevo." + except Exception as e: + error = f"Error al conectarse a la API: {e}" + + return render_template("index.html", chiste=chiste, error=error) + +@app.route('/salir') +def salir(): + return "

👋 ¡Gracias por reír con nosotros! Hasta la próxima.

" + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/jorge_luis_castellanos/jokes/templates/index.html b/clase3/jorge_luis_castellanos/jokes/templates/index.html new file mode 100644 index 0000000..ae97246 --- /dev/null +++ b/clase3/jorge_luis_castellanos/jokes/templates/index.html @@ -0,0 +1,64 @@ + + + + + + 😂 Chiste del Día + + + + + + + + + + + +
+
+
+
+
😂
+

Chiste del Día

+ + {% if error %} +
{{ error }}
+ {% else %} +

{{ chiste.setup }}

+

{{ chiste.punchline }}

+ {% endif %} + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/clase3/jorge_luis_castellanos/pokemon/app.py b/clase3/jorge_luis_castellanos/pokemon/app.py new file mode 100644 index 0000000..94dbb0f --- /dev/null +++ b/clase3/jorge_luis_castellanos/pokemon/app.py @@ -0,0 +1,54 @@ +import math + +import requests +from flask import Flask, render_template, request + +app = Flask(__name__) + +@app.route('/') +def index(): + page = int(request.args.get('page', 1)) + search = request.args.get('search', '').lower() + per_page = 9 + total_pokemons = 100 + offset = (page - 1) * per_page + pokemons = [] + + if search: + data = get_pokemon(search) + if data: + pokemons.append(data) + total_pages = 1 + else: + url = f'https://pokeapi.co/api/v2/pokemon?offset={offset}&limit={per_page}' + response = requests.get(url) + results = response.json().get('results', []) + for item in results: + poke_data = get_pokemon(item['name']) + if poke_data: + pokemons.append(poke_data) + total_pages = math.ceil(total_pokemons / per_page) + + return render_template('index.html', + pokemon_list=pokemons, + search_query=search, + page=page, + total_pages=total_pages) + +def get_pokemon(name): + url = f'https://pokeapi.co/api/v2/pokemon/{name}' + response = requests.get(url) + if response.status_code == 200: + data = response.json() + return { + 'name': data['name'].capitalize(), + 'image_front': data['sprites']['front_default'], + 'image_back': data['sprites']['back_default'], + 'height': data['height'], + 'weight': data['weight'], + 'abilities': [a['ability']['name'] for a in data['abilities']] + } + return None + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/jorge_luis_castellanos/pokemon/templates/index.html b/clase3/jorge_luis_castellanos/pokemon/templates/index.html new file mode 100644 index 0000000..a9d1ea8 --- /dev/null +++ b/clase3/jorge_luis_castellanos/pokemon/templates/index.html @@ -0,0 +1,59 @@ + + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+
+ Frente + Atrás +
+
+
{{ pokemon.name }}
+

+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }} +

+
+
+
+ {% endfor %} +
+ + + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + diff --git a/clase3/pablo_colcha/app.py b/clase3/pablo_colcha/app.py new file mode 100644 index 0000000..bdab683 --- /dev/null +++ b/clase3/pablo_colcha/app.py @@ -0,0 +1,51 @@ +from flask import Flask, render_template, request +import requests +import math +app = Flask(__name__) +POKEMONS_PER_PAGE = 10 + +@app.route("/", methods=["GET"]) +def index(): + search_query = request.args.get("search", "").lower() + page = int(request.args.get("page", 1)) + + offset = (page - 1) * POKEMONS_PER_PAGE + url = f"https://pokeapi.co/api/v2/pokemon?limit={POKEMONS_PER_PAGE}&offset={offset}" + response = requests.get(url) + + if response.status_code != 200: + return "error No se pudo obtener la lista de pokémones" + + results= response.json() + all_pokemon = [] + + for p in results["results"]: + poke_data = requests.get(p["url"]).json() + name = poke_data["name"] + + if search_query in name: + pokemon = { + "name": name.upper(), + "sprite": poke_data["sprites"]["front_default"], + "image": poke_data["sprites"]["other"]["showdown"]["back_shiny"], + "types": [t["type"]["name"] for t in poke_data["types"]], + "height": poke_data["height"], + "weight": poke_data["weight"], + "abilities": [a["ability"]["name"] for a in poke_data["abilities"]], + "stats": [s["stat"]["name"] for s in poke_data["stats"]][:3], + "moves": [m["move"]["name"] for m in poke_data["moves"]][:3], + "past_abilities": [a["generation"]["name"] for a in poke_data["past_abilities"]] + + } + all_pokemon.append(pokemon) + total=100 + total_pages = math.ceil(total / POKEMONS_PER_PAGE) + return render_template("index.html", + pokemon_list=all_pokemon, + search_query=search_query, + page=page, + total_pages=total_pages) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/clase3/pablo_colcha/templates/index.html b/clase3/pablo_colcha/templates/index.html new file mode 100644 index 0000000..47500e4 --- /dev/null +++ b/clase3/pablo_colcha/templates/index.html @@ -0,0 +1,61 @@ + + + + + + + Pokédex Flask + + + +
+

POKEAPI

+ +
+
+ + +
+
+ + {% if pokemon_list %} +
+ {% for pokemon in pokemon_list %} +
+
+ {{ pokemon.name }} +
+
{{ pokemon.name }}
+

+ Tipo: {{ pokemon.types | join(', ') }}
+ Altura: {{ pokemon.height }}
+ Peso: {{ pokemon.weight }}
+ Habilidades: {{ pokemon.abilities | join(', ') }}
+ Status: {{pokemon.stats | join(', ')}}
+ Movimientos:{{pokemon.moves |join (', ')}}
+ Generacion:{{pokemon.past_abilities | join(', ')}} +

+
+
+
+ {% endfor %} +
+ + + + + {% else %} +

No se encontraron Pokémon.

+ {% endif %} +
+ + + diff --git a/clase3/requirements.txt b/clase3/requirements.txt new file mode 100644 index 0000000..6e922de --- /dev/null +++ b/clase3/requirements.txt @@ -0,0 +1,13 @@ +blinker==1.9.0 +certifi==2025.7.9 +charset-normalizer==3.4.2 +click==8.2.1 +colorama==0.4.6 +Flask==3.1.1 +idna==3.10 +itsdangerous==2.2.0 +Jinja2==3.1.6 +MarkupSafe==3.0.2 +requests==2.32.4 +urllib3==2.5.0 +Werkzeug==3.1.3 diff --git a/clase3/ronald_diaz/app.py b/clase3/ronald_diaz/app.py new file mode 100644 index 0000000..b9dbd63 --- /dev/null +++ b/clase3/ronald_diaz/app.py @@ -0,0 +1,72 @@ +from flask import Flask, render_template, request, abort +import requests + +app = Flask(__name__) + +""" +Ejercicio 1:Comsumo Api Pokemon +""" + +API_BASE = "https://pokeapi.co/api/v2/pokemon" +PAGE_SIZE = 12 + +def listaPokemonesPage(page): + offset = (page - 1) * PAGE_SIZE + resp = requests.get(f"{API_BASE}?limit={PAGE_SIZE}&offset={offset}") + resp.raise_for_status() + data = resp.json() + return data['results'], bool(data['next']), bool(data['previous']) + +def obtenerPokemon(name): + resp = requests.get(f"{API_BASE}/{name.lower()}") + if resp.status_code == 404: + return None + resp.raise_for_status() + return resp.json() + +@app.route('/lista') +def listado(): + page = request.args.get('page', 1, type=int) + pokes, has_next, has_prev = listaPokemonesPage(page) + return render_template('listadoPokes.html', pokemons=pokes, page=page, has_next=has_next, has_prev=has_prev) + + +@app.route('/pokemon/') +def detalle(name): + p = obtenerPokemon(name) + if not p: + abort(404) + context = { + 'id': p['id'], + 'name': p['name'].capitalize(), + 'types': [t['type']['name'] for t in p['types']], + 'abilities': [a['ability']['name'] for a in p['abilities']], + 'height': p['height'], + 'weight': p['weight'], + 'base_experience': p['base_experience'], + 'stats': {s['stat']['name']: s['base_stat'] for s in p['stats']}, + 'sprite': p['sprites']['front_default'], + 'moves_count': len(p['moves']) + } + return render_template('detallePoke.html', **context) + +""" +Ejercicio 2 Consumo Api de chistes +""" +def obtener_chiste(): + resp = requests.get('https://official-joke-api.appspot.com/jokes/random') + resp.raise_for_status() + return resp.json() + +@app.route('/chistes') +def chistes(): + joke = obtener_chiste() + return render_template('chiste.html', setup=joke['setup'], punchline=joke['punchline']) + +@app.route('/') +def home(): + return render_template('index.html') + + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/clase3/ronald_diaz/templates/chiste.html b/clase3/ronald_diaz/templates/chiste.html new file mode 100644 index 0000000..3df8b69 --- /dev/null +++ b/clase3/ronald_diaz/templates/chiste.html @@ -0,0 +1,29 @@ + + + + + + Chistes Aleatorios + + + + +
+

Chiste Aleatorio

+
+
+

Setup: {{ setup }}

+

Punchline: {{ punchline }}

+
+
+ +
+ + + + \ No newline at end of file diff --git a/clase3/ronald_diaz/templates/detallePoke.html b/clase3/ronald_diaz/templates/detallePoke.html new file mode 100644 index 0000000..06ec11f --- /dev/null +++ b/clase3/ronald_diaz/templates/detallePoke.html @@ -0,0 +1,49 @@ + + + + + + Detalles de {{ name }} + + + + + +
+
+
+
+ Sprite de {{ name }} +
+
+
+

{{ name }} (ID: {{ id }})

+

Tipos: {{ types | join(', ') }}

+

Habilidades: {{ abilities | join(', ') }}

+

Altura: {{ height }} dm

+

Peso: {{ weight }} hg

+

Experiencia base: {{ base_experience }}

+
Estadísticas
+
    + {% for stat, val in stats.items() %} +
  • + {{ stat.capitalize() }} + {{ val }} +
  • + {% endfor %} +
+

Movimientos aprendidos: {{ moves_count }}

+ « Volver al listado +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/clase3/ronald_diaz/templates/index.html b/clase3/ronald_diaz/templates/index.html new file mode 100644 index 0000000..7115895 --- /dev/null +++ b/clase3/ronald_diaz/templates/index.html @@ -0,0 +1,35 @@ + + + + + + Trabajo Clase 3 Ronald Díaz + + + + +
+

Trabajo Clase 3 Ronald Díaz

+
+
+ +
+
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/clase3/ronald_diaz/templates/listadoPokes.html b/clase3/ronald_diaz/templates/listadoPokes.html new file mode 100644 index 0000000..9d9f77b --- /dev/null +++ b/clase3/ronald_diaz/templates/listadoPokes.html @@ -0,0 +1,69 @@ + + + + + + PokéBrowser + + + + + + +
+
+

Listado Pokémon

+
+ +
+ {% for p in pokemons %} +
+
+
+
{{ p.name }}
+ Ver detalles +
+
+
+ {% endfor %} +
+ + +
+ + + + + + \ No newline at end of file diff --git a/clase3/valeria_ramos/app.py b/clase3/valeria_ramos/app.py new file mode 100644 index 0000000..04e28d6 --- /dev/null +++ b/clase3/valeria_ramos/app.py @@ -0,0 +1,18 @@ +from flask import Flask, render_template +import requests + +app = Flask(__name__) + +@app.route('/') +def mostrar_chiste(): + url = "https://official-joke-api.appspot.com/jokes/random" + try: + response = requests.get(url) + response.raise_for_status() + data = response.json() + return render_template('index.html', setup=data['setup'], punchline=data['punchline']) + except Exception as e: + return f"Ocurrió un error: {e}" + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase3/valeria_ramos/templates/index.html b/clase3/valeria_ramos/templates/index.html new file mode 100644 index 0000000..f82137e --- /dev/null +++ b/clase3/valeria_ramos/templates/index.html @@ -0,0 +1,19 @@ + + + + Chiste Random + + + +
+

😂 Chiste Random

+
+

Chiste: {{ setup }}

+

Respuesta: {{ punchline }}

+
+ +
+
+
+ + diff --git a/clase3/valeria_ramos/valeria_ramos.py b/clase3/valeria_ramos/valeria_ramos.py new file mode 100644 index 0000000..3bcabb1 --- /dev/null +++ b/clase3/valeria_ramos/valeria_ramos.py @@ -0,0 +1,41 @@ +import requests + + +limit = 9 +offset = 0 + +while True: + url = f"https://pokeapi.co/api/v2/pokemon?limit={limit}&offset={offset}" + response = requests.get (url) + + if response.status_code == 200: + data = response.json() + print (f"Mostrando Pokemmón {offset+1} a {offset+limit}") + for poke in data ['results']: + print ("-", poke['name']) + else: + print ("Error al obtener datos.") + break + option = input ("Ver más.. (s/n):") + if option.lower() == 's': + offset += limit + else: + break +nombre = input ("\n Ingresa el nombre del Pokemón para ver sus datos:") + +url_pokemon = f"https://pokeapi.co/api/v2/pokemon/{nombre.lower()}" +resp_poke = requests.get(url_pokemon) + +if resp_poke.status_code == 200: + datos = resp_poke.json() + print("\nDatos del Pokémon:") + print("ID:", datos['id']) + print("Nombre:", datos['name']) + tipos = [t['type']['name'] for t in datos['types']] + print("Tipos:", tipos) + print("Altura:", datos['height']) + print("Imagen URL:", datos['sprites']['front_default']) + print("Sprite:", datos['sprites']['front_default']) +else: + print("Pokémon no encontrado.") + \ No newline at end of file diff --git a/clase4/chatbot_gemini.py b/clase4/chatbot_gemini.py new file mode 100644 index 0000000..2ab80b7 --- /dev/null +++ b/clase4/chatbot_gemini.py @@ -0,0 +1,62 @@ +import google.generativeai as ai +import os +from dotenv import load_dotenv + +load_dotenv() + +API_KEY = os.getenv("API_KEY_GEMINI") + +ai.configure(api_key=API_KEY) + +print("Checking available models for generateContent:") +model_to_use = None + +preferred_models = [ + "gemini-2.5-flash", + "gemini-2.5-flash-latest", + "gemini-2.5-flash-002", + "gemini-2.5-pro", + "gemini-2.5-pro-latest", + "gemini-2.5-pro-002", + "gemini-1.5-flash", + "gemini-1.5-flash-latest", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-latest", + "gemini-1.5-pro-002", +] + +available_models = [] +for m in ai.list_models(): + if "generateContent" in m.supported_generation_methods: + full_model_name = m.name + available_models.append(full_model_name) + print(f"- {full_model_name}") + +for preferred in preferred_models: + if f"models/{preferred}" in available_models: + model_to_use = f"models/{preferred}" + break + +if not model_to_use: + print("\nError: No suitable 'gemini' model found that supports 'generateContent' from the preferred list.") + print("Please review the available models printed above and manually update 'preferred_models' in the script.") + exit() +else: + print(f"\nUsing model: {model_to_use}") + model = ai.GenerativeModel(model_to_use) + +chat = model.start_chat() + +while True: + message = input('You: ') + if message.lower() == 'bye': + print('Chatbot: Goodbye!') + break + try: + response = chat.send_message(message) + print('Chatbot:', response.text) + except Exception as e: + print(f"An error occurred while sending message: {e}") + print("Please try again or restart the chat.") + \ No newline at end of file diff --git a/clase4/clase4.py b/clase4/clase4.py new file mode 100644 index 0000000..a02e46b --- /dev/null +++ b/clase4/clase4.py @@ -0,0 +1,49 @@ +# telebot_app.py + +from telebot import TeleBot, types +from dotenv import load_dotenv +import datetime + +load_dotenv() + +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +bot = TeleBot(BOT_TOKEN) + +# Estado temporal de los usuarios +user_data = {} + +@bot.message_handler(commands=['start']) +def start(message): + bot.send_message(message.chat.id, "👋 ¡Bienvenido al sistema de agendamiento de citas del SPA!\nPor favor, escribe tu nombre completo:") + bot.register_next_step_handler(message, process_name) + +def process_name(message): + user_data[message.chat.id] = {"name": message.text} + bot.send_message(message.chat.id, "¿Qué servicio deseas agendar? (Ej: masaje, facial, depilación)") + bot.register_next_step_handler(message, process_service) + +def process_service(message): + user_data[message.chat.id]["service"] = message.text + bot.send_message(message.chat.id, "¿Qué fecha deseas? (Formato: YYYY-MM-DD)") + bot.register_next_step_handler(message, process_date) + +def process_date(message): + try: + fecha = datetime.datetime.strptime(message.text, '%Y-%m-%d').date() + user_data[message.chat.id]["date"] = str(fecha) + bot.send_message(message.chat.id, "¿A qué hora? (Ej: 15:30)") + bot.register_next_step_handler(message, process_time) + except ValueError: + bot.send_message(message.chat.id, "Formato de fecha inválido. Intenta nuevamente (YYYY-MM-DD)") + bot.register_next_step_handler(message, process_date) + +def process_time(message): + user_data[message.chat.id]["time"] = message.text + data = user_data[message.chat.id] + resumen = f"📝 *Resumen de tu cita:*\nNombre: {data['name']}\nServicio: {data['service']}\nFecha: {data['date']}\nHora: {data['time']}" + bot.send_message(message.chat.id, resumen, parse_mode='Markdown') + bot.send_message(message.chat.id, "✅ ¡Tu cita ha sido registrada! Gracias por confiar en nuestro SPA ✨") + +if __name__ == "__main__": + print("Bot ejecutándose...") + bot.infinity_polling() \ No newline at end of file diff --git a/clase4/jazmin_rodriguez.py b/clase4/jazmin_rodriguez.py new file mode 100644 index 0000000..1e4b738 --- /dev/null +++ b/clase4/jazmin_rodriguez.py @@ -0,0 +1,17 @@ +from telebot import TeleBot + +TOKEN_BOT = '7217016747:AAF8wwtKCFcKFuO7DknBd1wyl8DLJ0EP-6w' + +bot = TeleBot(TOKEN_BOT) + +@bot.message_handler(commands=['start']) +def start(mensage): + print("Entro al start del bot") + bot.send_message("Bienvenido al SPA de Jazmin enque le podemos ayudar:") + bot.register_next_step_handler(mensage) + + +if __name__ == '__main__': + print("Esta ejecutandose el bot") + bot.infinity_polling() + \ No newline at end of file diff --git a/clase4/telebot.py b/clase4/telebot.py new file mode 100644 index 0000000..97cf391 --- /dev/null +++ b/clase4/telebot.py @@ -0,0 +1,265 @@ +from telegram import Update, ReplyKeyboardMarkup +from telegram.ext import ( + ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, + filters, ConversationHandler +) +from mailjet_rest import Client +import requests +import os +import re +import sqlite3 +from datetime import datetime +from dotenv import load_dotenv + +load_dotenv() + +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +MAILJET_API_KEY = os.getenv("MAILJET_API_KEY") +MAILJET_URL = os.getenv("MAILJET_URL") +MAILJET_API_SECRET = os.getenv("MAILJET_SECRET_KEY") +MAILJET_FROM_NAME = os.getenv("MAILJET_FROM_NAME") +EMAIL_FROM = os.getenv("EMAIL_FROM") + +MENU, DATOS, AUTORIZACION, CONFIRMAR, ACCION = range(4) + +SERVICIOS = { + "1. 🌐 Web App": 1000, + "2. 📱 Mobile App": 1200, + "3. 🔌 API REST": 800, + "4. 📋 Consultoría": 500 +} + +conn = sqlite3.connect("telebot_complete.db", check_same_thread=False) +cursor = conn.cursor() + +cursor.execute(""" +CREATE TABLE IF NOT EXISTS chat_data ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + username TEXT, + servicio TEXT, + message_id INTEGER, + timestamp TEXT +) +""") +conn.commit() + +def guardar_interaccion(update: Update): + user = update.effective_user + username = user.username or "Sin username" + servicio = update.message.text + message_id = update.message.message_id + timestamp = datetime.now().isoformat() + + cursor.execute(""" + INSERT INTO chat_data (user_id, username, servicio, message_id, timestamp) + VALUES (?, ?, ?, ?, ?) + """, (user.id, username, servicio, message_id, timestamp)) + conn.commit() + +# Inicio del bot +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + mensaje = ( + "🚀 Bienvenido al *Bot de Servicios de Software*.\n\n" + "Por favor, selecciona un servicio de la lista:" + ) + keyboard = [[opcion] for opcion in SERVICIOS.keys()] + await update.message.reply_text( + mensaje, + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + guardar_interaccion(update) + return MENU + +# Selección del servicio +async def seleccionar_servicio(update: Update, context: ContextTypes.DEFAULT_TYPE): + servicio = update.message.text.strip() + if servicio in SERVICIOS: + context.user_data["servicio"] = servicio + await update.message.reply_text( + f"📝 Has seleccionado *{servicio}*.\n\nAhora escribe:\n1. Tu nombre completo\n2. Tu correo electrónico\n3. Una breve descripción del proyecto", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return DATOS + else: + await update.message.reply_text("❌ Opción inválida. Selecciona un servicio del menú.") + return await start(update, context) + +# Recolección de datos +async def recibir_datos(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.strip() + email = extraer_email(texto) + if not email: + await update.message.reply_text( + "❌ No se detectó un correo válido.\nPor favor, escribe tus datos nuevamente en este formato:\n\n`Nombre - correo@ejemplo.com - descripción`", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return DATOS + + context.user_data["datos"] = texto + keyboard = [["✅ Sí", "❌ No"]] + await update.message.reply_text( + "🔐 ¿Autorizas el uso de tus datos para contactarte y procesar tu pedido?\nSelecciona una opción: \n✅ Sí / ❌ No", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True) + ) + guardar_interaccion(update) + return AUTORIZACION + +async def autorizacion(update: Update, context: ContextTypes.DEFAULT_TYPE): + respuesta = update.message.text.lower() + if "sí" in respuesta or "si" in respuesta or "✅" in respuesta: + servicio = context.user_data["servicio"] + precio = SERVICIOS[servicio] + keyboard = [["✅ Confirmar", "❌ Cancelar"]] + await update.message.reply_text( + f"💰 El precio de *{servicio}* es de *${precio}*.\n\n¿Deseas confirmar el pedido?\n✅ Confirmar / ❌ Cancelar", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + guardar_interaccion(update) + return CONFIRMAR + elif "no" in respuesta or "❌" in respuesta: + await update.message.reply_text("🚫 No podemos continuar sin tu autorización. Escribe /start para comenzar de nuevo.") + return ConversationHandler.END + else: + await update.message.reply_text("❌ Respuesta inválida. Selecciona *Sí* o *No* desde el menú.") + return AUTORIZACION + +# Confirmación del pedido +async def confirmar(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.lower() + guardar_interaccion(update) + if "confirmar" in texto or "✅" in texto: + servicio = context.user_data["servicio"] + descripcion = context.user_data["datos"] + precio = SERVICIOS[servicio] + correo = extraer_email(descripcion) + + mensaje = ( + f"🎉 *Gracias por tu pedido!*\n\n" + f"✅ *Servicio:* {servicio}\n" + f"📝 *Descripción:* {descripcion}\n" + f"💵 *Precio:* ${precio}\n\n" + "Nos pondremos en contacto contigo pronto. 📧" + ) + + print("email", descripcion, precio, correo) + print("mensaje", mensaje) + + if correo: + enviado = enviar_mailjet(context, correo, MAILJET_FROM_NAME + " Confirmación de tu pedido", mensaje) + if enviado: + await update.message.reply_text("📧 Correo de confirmación enviado con éxito ✅") + else: + await update.message.reply_text("⚠️ Hubo un error al enviar el correo.") + else: + await update.message.reply_text("⚠️ El correo no se detectó correctamente. No se envió el correo.") + + await update.message.reply_text("¿Necesitas algo más? Escribe /start para hacer otro pedido.") + return ConversationHandler.END + elif "cancelar" in texto or "❌" in texto: + await update.message.reply_text("❌ Pedido cancelado. Si deseas iniciar de nuevo, escribe /start.") + return ConversationHandler.END + else: + await update.message.reply_text("❌ Respuesta inválida. Selecciona *Confirmar* o *Cancelar* desde el menú.") + return MENU + +# Extraer correo desde un texto +def extraer_email(texto): + match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', texto) + return match.group(0) if match else None + +def enviar_mailjet(context, destinatario, asunto, contenido): + # data = { + # 'Messages': [ + # { + # "From": { + # "Email": EMAIL_FROM, + # "Name": "Servicios de Software" + # }, + # "To": [ + # { + # "Email": destinatario, + # "Name": "Cliente" + # } + # ], + # "Subject": asunto, + # "TextPart": contenido + # } + # ] + # } + + data = { + "Messages": [ + { + "From": { + "Email": os.getenv("EMAIL_FROM"), + "Name": "Servicios de Software" + }, + "To": [ + { + "Email": destinatario, + "Name": "Cliente" + } + ], + "Subject": asunto, + "HTMLPart": f""" +
+

🎉 ¡Gracias por tu pedido!

+

Servicio: {context.user_data['servicio']}

+

📝 Descripción: {context.user_data['datos']}

+

💵 Precio: ${SERVICIOS[context.user_data['servicio']]}

+ + Gracias por tu pedido + +

Haz clic en el botón para visitar nuestra página:

+ + Ir a la página 🚀 + + +
+ """ + } + ] + } + + try: + response = requests.post( + MAILJET_URL, + json=data, + auth=(MAILJET_API_KEY, MAILJET_API_SECRET), + timeout=(3.05, 5) + ) + print(f"📨 Mailjet response: {response.status_code} - {response.text}") + return response.status_code == 200 + except Exception as e: + print(f"❌ Error enviando correo con Mailjet: {e}") + return False + +# Main +def main(): + app = ApplicationBuilder().token(BOT_TOKEN).build() + + conv_handler = ConversationHandler( + entry_points=[CommandHandler("start", start)], + states={ + MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, seleccionar_servicio)], + DATOS: [MessageHandler(filters.TEXT & ~filters.COMMAND, recibir_datos)], + AUTORIZACION: [MessageHandler(filters.TEXT & ~filters.COMMAND, autorizacion)], + CONFIRMAR: [MessageHandler(filters.TEXT & ~filters.COMMAND, confirmar)], + }, + fallbacks=[], + ) + + app.add_handler(conv_handler) + print("🤖 Bot en ejecución...") + app.run_polling() + +if __name__ == "__main__": + main() diff --git a/clase4/web_bot/app.py b/clase4/web_bot/app.py new file mode 100644 index 0000000..38ef279 --- /dev/null +++ b/clase4/web_bot/app.py @@ -0,0 +1,93 @@ +from flask import Flask, render_template, request, redirect, url_for +import sqlite3 +import os +from dotenv import load_dotenv +import google.generativeai as ai + +load_dotenv() +API_KEY = os.getenv("API_KEY_GEMINI") +ai.configure(api_key=API_KEY) + +preferred_models = [ + "gemini-2.5-flash", + "gemini-2.5-flash-latest", + "gemini-2.5-flash-002", + "gemini-1.5-flash", + "gemini-1.5-flash-latest", + "gemini-1.5-flash-002", +] + +model_to_use = None +for m in ai.list_models(): + if "generateContent" in m.supported_generation_methods: + for preferred in preferred_models: + if m.name == f"models/{preferred}": + model_to_use = m.name + break + if model_to_use: + break + +if not model_to_use: + raise Exception("No Gemini model available for generateContent") + +model = ai.GenerativeModel(model_to_use) +chat = model.start_chat() + +# --- Flask Setup --- +app = Flask(__name__) +DATABASE = 'chat.db' + +# --- Database Helper Functions --- +def init_db(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute(''' + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_message TEXT NOT NULL, + bot_response TEXT NOT NULL, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP + ) + ''') + conn.commit() + conn.close() + +init_db() + +@app.route('/') +def index(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("SELECT user_message, bot_response, timestamp FROM messages ORDER BY id ASC") + chat_history = c.fetchall() + conn.close() + return render_template('index.html', chat_history=chat_history) + +@app.route('/send', methods=['POST']) +def send(): + user_message = request.form['message'] + try: + response = chat.send_message(user_message) + bot_response = response.text + except Exception as e: + bot_response = f"Error: {e}" + + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("INSERT INTO messages (user_message, bot_response) VALUES (?, ?)", (user_message, bot_response)) + conn.commit() + conn.close() + + return redirect(url_for('index')) + +@app.route('/clear') +def clear(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("DELETE FROM messages") + conn.commit() + conn.close() + return redirect(url_for('index')) + +if __name__ == '__main__': + app.run(debug=True) diff --git a/clase4/web_bot/templates/index.html b/clase4/web_bot/templates/index.html new file mode 100644 index 0000000..1390477 --- /dev/null +++ b/clase4/web_bot/templates/index.html @@ -0,0 +1,39 @@ + + + + + 🤖 Chatbot con Gemini + + + + +
+

💬 Chatbot con Gemini AI

+ +
+
+ {% for user_msg, bot_msg, timestamp in chat_history %} +
Tú: {{ user_msg }}
+
Bot: {{ bot_msg }}
+ {% endfor %} +
+
+ +
+ + +
+ + +
+ + diff --git a/entorno/Scripts/Activate.ps1 b/entorno/Scripts/Activate.ps1 new file mode 100644 index 0000000..918eac3 --- /dev/null +++ b/entorno/Scripts/Activate.ps1 @@ -0,0 +1,528 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" + +# SIG # Begin signature block +# MII0CQYJKoZIhvcNAQcCoIIz+jCCM/YCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk +# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCG9IwggXMMIIDtKADAgECAhBUmNLR1FsZ +# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK +# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu +# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy +# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT +# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv +# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo +# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD +# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH +# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD +# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV +# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70 +# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1 +# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3 +# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK +# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg +# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj +# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7 +# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE +# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ +# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn +# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c +# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF +# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx +# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8 +# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY +# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2 +# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY +# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al +# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk +# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T +# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggb+MIIE5qADAgECAhMzAAM/y2Wy +# WWnFfpZcAAAAAz/LMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD +# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ +# RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDEwHhcNMjUwNDA4MDEwNzI0WhcNMjUwNDEx +# MDEwNzI0WjB8MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQH +# EwlCZWF2ZXJ0b24xIzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9u +# MSMwIQYDVQQDExpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAaIwDQYJKoZI +# hvcNAQEBBQADggGPADCCAYoCggGBAI0elXEcbTdGLOszMU2fzimHGM9Y4EjwFgC2 +# iGPdieHc0dK1DyEIdtnvjKxnG/KICC3J2MrhePGzMEkie3yQjx05B5leG0q8YoGU +# m9z9K67V6k3DSXX0vQe9FbaNVuyXed31MEf/qek7Zo4ELxu8n/LO3ibURBLRHNoW +# Dz9zr4DcU+hha0bdIL6SnKMLwHqRj59gtFFEPqXcOVO7kobkzQS3O1T5KNL/zGuW +# UGQln7fS4YI9bj24bfrSeG/QzLgChVYScxnUgjAANfT1+SnSxrT4/esMtfbcvfID +# BIvOWk+FPPj9IQWsAMEG/LLG4cF/pQ/TozUXKx362GJBbe6paTM/RCUTcffd83h2 +# bXo9vXO/roZYk6H0ecd2h2FFzLUQn/0i4RQQSOp6zt1eDf28h6F8ev+YYKcChph8 +# iRt32bJPcLQVbUzhehzT4C0pz6oAqPz8s0BGvlj1G6r4CY1Cs2YiMU09/Fl64pWf +# IsA/ReaYj6yNsgQZNUcvzobK2mTxMwIDAQABo4ICGTCCAhUwDAYDVR0TAQH/BAIw +# ADAOBgNVHQ8BAf8EBAMCB4AwPAYDVR0lBDUwMwYKKwYBBAGCN2EBAAYIKwYBBQUH +# AwMGGysGAQQBgjdhgqKNuwqmkohkgZH0oEWCk/3hbzAdBgNVHQ4EFgQU4Y4Xr/Xn +# zEXblXrNC0ZLdaPEJYUwHwYDVR0jBBgwFoAU6IPEM9fcnwycdpoKptTfh6ZeWO4w +# ZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w +# cy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwQU9DJTIwQ0El +# MjAwMS5jcmwwgaUGCCsGAQUFBwEBBIGYMIGVMGQGCCsGAQUFBzAChlhodHRwOi8v +# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw +# VmVyaWZpZWQlMjBDUyUyMEFPQyUyMENBJTIwMDEuY3J0MC0GCCsGAQUFBzABhiFo +# dHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwZgYDVR0gBF8wXTBRBgwr +# BgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu +# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEEATANBgkqhkiG +# 9w0BAQwFAAOCAgEAKTeVGPXsDKqQLe1OuKx6K6q711FPxNQyLOOqeenH8zybHwNo +# k05cMk39HQ7u+R9BQIL0bWexb7wa3XeKaX06p7aY/OQs+ycvUi/fC6RGlaLWmQ9D +# YhZn2TBz5znimvSf3P+aidCuXeDU5c8GpBFog6fjEa/k+n7TILi0spuYZ4yC9R48 +# R63/VvpLi2SqxfJbx5n92bY6driNzAntjoravF25BSejXVrdzefbnqbQnZPB39g8 +# XHygGPb0912fIuNKPLQa/uCnmYdXJnPb0ZgMxxA8fyxvL2Q30Qf5xpFDssPDElvD +# DoAbvR24CWvuHbu+CMMr2SJUpX4RRvDioO7JeB6wZb+64MXyPUSSf6QwkKNsHPIa +# e9tSfREh86sYn5bOA0Wd+Igk0RpA5jDRTu3GgPOPWbm1PU+VoeqThtHt6R3l17pr +# aQ5wIuuLXgxi1K4ZWgtvXw8BtIXfZz24qCtoo0+3kEGUpEHBgkF1SClbRb8uAzx+ +# 0ROGniLPJRU20Xfn7CgipeKLcNn33JPFwQHk1zpbGS0090mi0erOQCz0S47YdHmm +# RJcbkNIL9DeNAglTZ/TFxrYUM1NRS1Cp4e63MgBKcWh9VJNokInzzmS+bofZz+u1 +# mm8YNtiJjdT8fmizXdUEk68EXQhOs0+HBNvc9nMRK6R28MZu/J+PaUcPL84wggda +# MIIFQqADAgECAhMzAAAABzeMW6HZW4zUAAAAAAAHMA0GCSqGSIb3DQEBDAUAMGMx +# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAy +# BgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIw +# MjEwHhcNMjEwNDEzMTczMTU0WhcNMjYwNDEzMTczMTU0WjBaMQswCQYDVQQGEwJV +# UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNy +# b3NvZnQgSUQgVmVyaWZpZWQgQ1MgQU9DIENBIDAxMIICIjANBgkqhkiG9w0BAQEF +# AAOCAg8AMIICCgKCAgEAt/fAAygHxbo+jxA04hNI8bz+EqbWvSu9dRgAawjCZau1 +# Y54IQal5ArpJWi8cIj0WA+mpwix8iTRguq9JELZvTMo2Z1U6AtE1Tn3mvq3mywZ9 +# SexVd+rPOTr+uda6GVgwLA80LhRf82AvrSwxmZpCH/laT08dn7+Gt0cXYVNKJORm +# 1hSrAjjDQiZ1Jiq/SqiDoHN6PGmT5hXKs22E79MeFWYB4y0UlNqW0Z2LPNua8k0r +# bERdiNS+nTP/xsESZUnrbmyXZaHvcyEKYK85WBz3Sr6Et8Vlbdid/pjBpcHI+Hyt +# oaUAGE6rSWqmh7/aEZeDDUkz9uMKOGasIgYnenUk5E0b2U//bQqDv3qdhj9UJYWA +# DNYC/3i3ixcW1VELaU+wTqXTxLAFelCi/lRHSjaWipDeE/TbBb0zTCiLnc9nmOjZ +# PKlutMNho91wxo4itcJoIk2bPot9t+AV+UwNaDRIbcEaQaBycl9pcYwWmf0bJ4IF +# n/CmYMVG1ekCBxByyRNkFkHmuMXLX6PMXcveE46jMr9syC3M8JHRddR4zVjd/FxB +# nS5HOro3pg6StuEPshrp7I/Kk1cTG8yOWl8aqf6OJeAVyG4lyJ9V+ZxClYmaU5yv +# tKYKk1FLBnEBfDWw+UAzQV0vcLp6AVx2Fc8n0vpoyudr3SwZmckJuz7R+S79BzMC +# AwEAAaOCAg4wggIKMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAd +# BgNVHQ4EFgQU6IPEM9fcnwycdpoKptTfh6ZeWO4wVAYDVR0gBE0wSzBJBgRVHSAA +# MEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv +# RG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAS +# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRI +# ajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w +# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2ln +# bmluZyUyMFBDQSUyMDIwMjEuY3JsMIGuBggrBgEFBQcBAQSBoTCBnjBtBggrBgEF +# BQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy +# b3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAy +# MDIxLmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3AubWljcm9zb2Z0LmNv +# bS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQB3/utLItkwLTp4Nfh99vrbpSsL8NwP +# Ij2+TBnZGL3C8etTGYs+HZUxNG+rNeZa+Rzu9oEcAZJDiGjEWytzMavD6Bih3nEW +# FsIW4aGh4gB4n/pRPeeVrK4i1LG7jJ3kPLRhNOHZiLUQtmrF4V6IxtUFjvBnijaZ +# 9oIxsSSQP8iHMjP92pjQrHBFWHGDbkmx+yO6Ian3QN3YmbdfewzSvnQmKbkiTibJ +# gcJ1L0TZ7BwmsDvm+0XRsPOfFgnzhLVqZdEyWww10bflOeBKqkb3SaCNQTz8nsha +# UZhrxVU5qNgYjaaDQQm+P2SEpBF7RolEC3lllfuL4AOGCtoNdPOWrx9vBZTXAVdT +# E2r0IDk8+5y1kLGTLKzmNFn6kVCc5BddM7xoDWQ4aUoCRXcsBeRhsclk7kVXP+zJ +# GPOXwjUJbnz2Kt9iF/8B6FDO4blGuGrogMpyXkuwCC2Z4XcfyMjPDhqZYAPGGTUI +# NMtFbau5RtGG1DOWE9edCahtuPMDgByfPixvhy3sn7zUHgIC/YsOTMxVuMQi/bga +# memo/VNKZrsZaS0nzmOxKpg9qDefj5fJ9gIHXcp2F0OHcVwe3KnEXa8kqzMDfrRl +# /wwKrNSFn3p7g0b44Ad1ONDmWt61MLQvF54LG62i6ffhTCeoFT9Z9pbUo2gxlyTF +# g7Bm0fgOlnRfGDCCB54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJ +# KoZIhvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBD +# b3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNh +# dGlvbiBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIw +# MDUyMFoXDTM2MDQwMTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1p +# Y3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlm +# aWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +# ADCCAgoCggIBALLwwK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3 +# qrZilYKJNqztA9OQacr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrw +# eLoQ71lzCHkD7A4As1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9 +# rGQ//h890Q8JdjLLw0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8s +# ZU6ZE7iRrRZywRmrKDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfW +# o5tTgkoSMoayqoDpHOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC6 +# 9oKpRQXY9bGH6jn9NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjk +# Vd6CGUAf0K+Jw+GE/5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHg +# YYjHs1NbOc6brH+eKpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu +# 0t+gCwLdN0A6cFtSRtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeL +# zdpt32cdYKp+dhr2ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGj +# ggI1MIICMTAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0O +# BBYEFNlBKbAPD2Ns72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8G +# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv +# UmVwb3NpdG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0T +# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYD +# VR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j +# cmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIw +# Q2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEE +# gbYwgbMwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp +# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw +# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYB +# BQUHMAGGIWh0dHA6Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG +# 9w0BAQwFAAOCAgEAfyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdP +# Q4H55v7VOInnmezQEeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVI +# E1CRFfNF4XKO8XYEa3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T +# 8FG7/VEURIVWArbAzPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4 +# e0ejRA7mB2IoX5hNh3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaB +# jhWmirYyANb0RJSLWjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/t +# uLjAsKP6SzYZ+1Ry358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQw +# K8VtsBdekBmdTbQVoCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX +# 3mccFgx6UsQeRSdVVVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQL +# Uz6ZTl65yPUiOh3k7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i +# 3IpaDcR+iuGjH2TdaC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxgheN +# MIIXiQIBATBxMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y +# cG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBBT0Mg +# Q0EgMDECEzMAAz/LZbJZacV+llwAAAADP8swDQYJYIZIAWUDBAIBBQCggcowGQYJ +# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB +# gjcCARUwLwYJKoZIhvcNAQkEMSIEIGcBno/ti9PCrR9sXrajsTvlHQvGxbk63JiI +# URJByQuGMF4GCisGAQQBgjcCAQwxUDBOoEiARgBCAHUAaQBsAHQAOgAgAFIAZQBs +# AGUAYQBzAGUAXwB2ADMALgAxADIALgAxADAAXwAyADAAMgA1ADAANAAwADgALgAw +# ADKhAoAAMA0GCSqGSIb3DQEBAQUABIIBgE9xMVem4h5iAbvBzmB1pTdA4LYNkvd/ +# hSbYmJRt5oJqBR0RGbUmcfYAgTlhdb/S84aGvI3N62I8qeMApnH89q+UF0i8p6+U +# Qza6Mu1cAHCq0NkHH6+N8g7nIfe5Cn+BBCBJ6kuYfQm9bx1JwEm5/yVCwG9I6+XV +# 3WonOeA8djuZFfB9OIW6N9ubX7X+nYqWaeT6w6/lDs8mL+s0Fumy4mJ8B15pd9mr +# N6dIRFokzhuALq6G0USKFzYf3qJQ4GyCos/Luez3cr8sE/78ds6vah5IlLP6qXMM +# ETwAdoymIYSm3Dly3lflodd4d7/nkMhfHITOxSUDoBbCP6MO1rhChX591rJy/omK +# 0RdM9ZpMl6VXHhzZ+lB8U/6j7xJGlxJSJHet7HFEuTnJEjY9dDy2bUgzk0vK1Rs2 +# l7VLOP3X87p9iVz5vDAOQB0fcsMDJvhIzJlmIb5z2uZ6hqD4UZdTDMLIBWe9H7Kv +# rhmGDPHPRboFKtTrKoKcWaf4fJJ2NUtYlKGCFKAwghScBgorBgEEAYI3AwMBMYIU +# jDCCFIgGCSqGSIb3DQEHAqCCFHkwghR1AgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFh +# BgsqhkiG9w0BCRABBKCCAVAEggFMMIIBSAIBAQYKKwYBBAGEWQoDATAxMA0GCWCG +# SAFlAwQCAQUABCAY3nVyqXzzboHwsVGd+j5FjG9eaMv+O3mJKpX+3EJ43AIGZ9gU +# uyvYGBMyMDI1MDQwODEyNDEyMi40MTNaMASAAgH0oIHgpIHdMIHaMQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg +# QW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1 +# LTk2M0ItRTFGNDE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBT +# dGFtcGluZyBBdXRob3JpdHmggg8gMIIHgjCCBWqgAwIBAgITMwAAAAXlzw//Zi7J +# hwAAAAAABTANBgkqhkiG9w0BAQwFADB3MQswCQYDVQQGEwJVUzEeMBwGA1UEChMV +# TWljcm9zb2Z0IENvcnBvcmF0aW9uMUgwRgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRp +# dHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAw +# HhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5MjA0MjMxWjBhMQswCQYDVQQGEwJVUzEe +# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv +# ZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDCCAiIwDQYJKoZIhvcN +# AQEBBQADggIPADCCAgoCggIBAJ5851Jj/eDFnwV9Y7UGIqMcHtfnlzPREwW9ZUZH +# d5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqOQxwuEQXG8kB41wsDJP5d0zmLYKAY8Zxv +# 3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEESnt0MbPEoKdNihwM5xGv0rGofJ1qOYST +# Ncc55EbBT7uq3wx3mXhtVmtcCEr5ZKTkKKE1CxZvNPWdGWJUPC6e4uRfWHIhZcgC +# sJ+sozf5EeH5KrlFnxpjKKTavwfFP6XaGZGWUG8TZaiTogRoAlqcevbiqioUz1Yt +# 4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm5sOTiEQtBLGd9Vhd1MadxoGcHrRCsS5r +# O9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+eZ4CNE3ctW4uvSDQVeSp9h1SaPV8UWEf +# yTxgGjOsRpeexIveR1MPTVf7gt8hY64XNPO6iyUGsEgt8c2PxF87E+CO7A28TpjN +# q5eLiiunhKbq0XbjkNoU5JhtYUrlmAbpxRjb9tSreDdtACpm3rkpxp7AQndnI0Sh +# u/fk1/rE3oWsDqMX3jjv40e8KN5YsJBnczyWB4JyeeFMW3JBfdeAKhzohFe8U5w9 +# WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8Y5SwB1lt5dQhABYyzR3dxEO/T1K/BVF3 +# rV69AgMBAAGjggIbMIICFzAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMC +# AQAwHQYDVR0OBBYEFGtpKDo1L0hjQM972K9J6T7ZPdshMFQGA1UdIARNMEswSQYE +# VR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp +# b3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJ +# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +# GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0 +# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl +# bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo +# b3JpdHklMjAyMDIwLmNybDCBlAYIKwYBBQUHAQEEgYcwgYQwgYEGCCsGAQUFBzAC +# hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m +# dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl +# JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwDQYJKoZIhvcNAQEMBQADggIBAF+Idsd+ +# bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/pO+4ge/XEizXvhs0Y7+KVYyb4nHlugBes +# nFqBGEdC2IWmtKMyS1OWIviwpnK3aL5JedwzbeBF7POyg6IGG/XhhJ3UqWeWTO+C +# zb1c2NP5zyEh89F72u9UIw+IfvM9lzDmc2O2END7MPnrcjWdQnrLn1Ntday7JSyr +# DvBdmgbNnCKNZPmhzoa8PccOiQljjTW6GePe5sGFuRHzdFt8y+bN2neF7Zu8hTO1 +# I64XNGqst8S+w+RUdie8fXC1jKu3m9KGIqF4aldrYBamyh3g4nJPj/LR2CBaLyD+ +# 2BuGZCVmoNR/dSpRCxlot0i79dKOChmoONqbMI8m04uLaEHAv4qwKHQ1vBzbV/nG +# 89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFfR4f/gksSkbJp7oqLwliDm/h+w0aJ/U5c +# cnYhYb7vPKNMN+SZDWycU5ODIRfyoGl59BsXR/HpRGtiJquOYGmvA/pk5vC1lcnb +# eMrcWD/26ozePQ/TWfNXKBOmkFpvPE8CH+EeGGWzqTCjdAsno2jzTeNSxlx3glDG +# Jgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqPTXPmaCAJKVHAP19oEjJIBwD1LyHbaEgB +# xFCogYSOiUIr0Xqcr1nJfiWG2GwYe6ZoAF1bMIIHljCCBX6gAwIBAgITMwAAAEYX +# 5HV6yv3a5QAAAAAARjANBgkqhkiG9w0BAQwFADBhMQswCQYDVQQGEwJVUzEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQg +# UHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAeFw0yNDExMjYxODQ4NDla +# Fw0yNTExMTkxODQ4NDlaMIHaMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu +# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv +# cmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYw +# JAYDVQQLEx1UaGFsZXMgVFNTIEVTTjozREE1LTk2M0ItRTFGNDE1MDMGA1UEAxMs +# TWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHkwggIi +# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwlXzoj/MNL1BfnV+gg4d0fZum +# 1HdUJidSNTcDzpHJvmIBqH566zBYcV0TyN7+3qOnJjpoTx6JBMgNYnL5BmTX9Hrm +# X0WdNMLf74u7NtBSuAD2sf6n2qUUrz7i8f7r0JiZixKJnkvA/1akLHppQMDCug1o +# C0AYjd753b5vy1vWdrHXE9hL71BZe5DCq5/4LBny8aOQZlzvjewgONkiZm+Sfctk +# Jjh9LxdkDlq5EvGE6YU0uC37XF7qkHvIksD2+XgBP0lEMfmPJo2fI9FwIA9YMX7K +# IINEM5OY6nkvKryM9s5bK6LV4z48NYpiI1xvH15YDps+19nHCtKMVTZdB4cYhA0d +# VqJ7dAu4VcxUwD1AEcMxWbIOR1z6OFkVY9GX5oH8k17d9t35PWfn0XuxW4SG/rim +# gtFgpE/shRsy5nMCbHyeCdW0He1plrYQqTsSHP2n/lz2DCgIlnx+uvPLVf5+JG/1 +# d1i/LdwbC2WH6UEEJyZIl3a0YwM4rdzoR+P4dO9I/2oWOxXCYqFytYdCy9ljELUw +# byLjrjRddteR8QTxrCfadKpKfFY6Ak/HNZPUHaAPak3baOIvV7Q8axo3DWQy2ib3 +# zXV6hMPNt1v90pv+q9daQdwUzUrgcbwThdrRhWHwlRIVg2sR668HPn4/8l9ikGok +# rL6gAmVxNswEZ9awCwIDAQABo4IByzCCAccwHQYDVR0OBBYEFBE20NSvdrC6Z6cm +# 6RPGP8YbqIrxMB8GA1UdIwQYMBaAFGtpKDo1L0hjQM972K9J6T7ZPdshMGwGA1Ud +# HwRlMGMwYaBfoF2GW2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js +# L01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIw +# MjAyMC5jcmwweQYIKwYBBQUHAQEEbTBrMGkGCCsGAQUFBzAChl1odHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFB1YmxpYyUy +# MFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5jcnQwDAYDVR0TAQH/BAIw +# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0g +# BF8wXTBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t +# aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEE +# AjANBgkqhkiG9w0BAQwFAAOCAgEAFIW5L+gGzX4gyHorS33YKXuK9iC91iZTpm30 +# x/EdHG6U8NAu2qityxjZVq6MDq300gspG0ntzLYqVhjfku7iNzE78k6tNgFCr9wv +# GkIHeK+Q2RAO9/s5R8rhNC+lywOB+6K5Zi0kfO0agVXf7Nk2O6F6D9AEzNLijG+c +# Oe5Ef2F5l4ZsVSkLFCI5jELC+r4KnNZjunc+qvjSz2DkNsXfrjFhyk+K7v7U7+JF +# Z8kZ58yFuxEX0cxDKpJLxiNh/ODCOL2UxYkhyfI3AR0EhfxX9QZHVgxyZwnavR35 +# FxqLSiGTeAJsK7YN3bIxyuP6eCcnkX8TMdpu9kPD97sHnM7po0UQDrjaN7etviLD +# xnax2nemdvJW3BewOLFrD1nSnd7ZHdPGPB3oWTCaK9/3XwQERLi3Xj+HZc89RP50 +# Nt7h7+3G6oq2kXYNidI9iWd+gL+lvkQZH9YTIfBCLWjvuXvUUUU+AvFI00Utqrvd +# rIdqCFaqE9HHQgSfXeQ53xLWdMCztUP/YnMXiJxNBkc6UE2px/o6+/LXJDIpwIXR +# 4HSodLfkfsNQl6FFrJ1xsOYGSHvcFkH8389RmUvrjr1NBbdesc4Bu4kox+3cabOZ +# c1zm89G+1RRL2tReFzSMlYSGO3iKn3GGXmQiRmFlBb3CpbUVQz+fgxVMfeL0j4Lm +# KQfT1jIxggPUMIID0AIBATB4MGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNB +# IFRpbWVzdGFtcGluZyBDQSAyMDIwAhMzAAAARhfkdXrK/drlAAAAAABGMA0GCWCG +# SAFlAwQCAQUAoIIBLTAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZI +# hvcNAQkEMSIEIHgwQkiMhul6IrfEKmPaCFR+R91oZOlPqVgP/9PPcfn+MIHdBgsq +# hkiG9w0BCRACLzGBzTCByjCBxzCBoAQgEid2SJpUPj5xQm73M4vqDmVh1QR6TiuT +# UVkL3P8Wis4wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m +# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGlt +# ZXN0YW1waW5nIENBIDIwMjACEzMAAABGF+R1esr92uUAAAAAAEYwIgQgVp6I1YBM +# Mni0rCuD57vEK/tzWZypHqWFikWLFVY11RwwDQYJKoZIhvcNAQELBQAEggIAnRBH +# voM5+wbJp+aOwrrL8fi8Rv/eFV820Nhr+jMny73UscN60OWdcdcZDbjDlnDX1KEP +# sNcEOFvaruHHrF4kDK8N0yemElNz63IgqhUoGoXXQKT2RgVg7T/kiQJH7zuaEjgB +# YNniAZdXXJJ1C+uv2ZQzkGIEVIEA6pB5/xo4kFhrfkOrdGzqL8HXT/RZQDMn5Uzk +# W+Sl2JmsyYBS4sgI9Ay3qT5nv+frzngbWlqx1dre21uj37Fgk5mWHJEdmY1nqTTd +# 25j6oDLGPC8AS9wtgZBXggemKAXwyeOFFahXUFN7X7cbwTALy5aWjE/rqp+N5J7M +# +YApl3aknUZ13KTXz9pfAF0uhmZimngvBHjijyctleF8HUP2RNAhS/l68OqW7oKi +# Dqvb7tSHJbcnYkxo7dUq6ppfN51ah61ZsyMVG6SaH015+5QO1k50ohXcFff2GOuZ +# d3Z9JOoAjIkeiVTNeRlPDlHtS0CSYu4ZKsWsst+0VY2R9rJBeoii9Xa0oiIggkYL +# 1pHAPH0B1uLlvFcI6B+fAXe0OiCJodbO5lk8ZpvCG5WWYbjzp2c3B8PZGSBgEpSf +# KYlVavvBAvaJCORUO7j8PyzzDINuzQorP9+i399ORjOnqeC92Cb0V12LcoqqtJaf +# 7oSB86VOI0lfHnPUlLWvoiLHrFR5PsYkltOuPqU= +# SIG # End signature block diff --git a/entorno/Scripts/activate b/entorno/Scripts/activate new file mode 100644 index 0000000..8309a12 --- /dev/null +++ b/entorno/Scripts/activate @@ -0,0 +1,76 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past locations. Without forgetting + # past locations the $PATH changes we made may not be respected. + # See "man bash" for more details. hash is usually a builtin of your shell + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +case "$(uname)" in + CYGWIN*|MSYS*|MINGW*) + # transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW + # and to /cygdrive/d/path/to/venv on Cygwin + VIRTUAL_ENV=$(cygpath 'C:\Users\DELL13\Desktop\CURSO CHATBOT CON PYTHON\CLASES DE ESTE CURSO\python_telebots\entorno') + export VIRTUAL_ENV + ;; + *) + # use the path as-is + export VIRTUAL_ENV='C:\Users\DELL13\Desktop\CURSO CHATBOT CON PYTHON\CLASES DE ESTE CURSO\python_telebots\entorno' + ;; +esac + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/"Scripts":$PATH" +export PATH + +VIRTUAL_ENV_PROMPT='(entorno) ' +export VIRTUAL_ENV_PROMPT + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="("'(entorno) '") ${PS1:-}" + export PS1 +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/entorno/Scripts/activate.bat b/entorno/Scripts/activate.bat new file mode 100644 index 0000000..ba7ffa6 --- /dev/null +++ b/entorno/Scripts/activate.bat @@ -0,0 +1,34 @@ +@echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set _OLD_CODEPAGE=%%a +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + +set "VIRTUAL_ENV=C:\Users\DELL13\Desktop\CURSO CHATBOT CON PYTHON\CLASES DE ESTE CURSO\python_telebots\entorno" + +if not defined PROMPT set PROMPT=$P$G + +if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% +if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% + +set _OLD_VIRTUAL_PROMPT=%PROMPT% +set PROMPT=(entorno) %PROMPT% + +if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +set PYTHONHOME= + +if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% +if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% + +set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" +set "VIRTUAL_ENV_PROMPT=(entorno) " + +:END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set _OLD_CODEPAGE= +) diff --git a/entorno/Scripts/deactivate.bat b/entorno/Scripts/deactivate.bat new file mode 100644 index 0000000..62a39a7 --- /dev/null +++ b/entorno/Scripts/deactivate.bat @@ -0,0 +1,22 @@ +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= +set VIRTUAL_ENV_PROMPT= + +:END diff --git a/entorno/Scripts/dotenv.exe b/entorno/Scripts/dotenv.exe new file mode 100644 index 0000000..793faec Binary files /dev/null and b/entorno/Scripts/dotenv.exe differ diff --git a/entorno/Scripts/flask.exe b/entorno/Scripts/flask.exe new file mode 100644 index 0000000..55ef6a2 Binary files /dev/null and b/entorno/Scripts/flask.exe differ diff --git a/entorno/Scripts/normalizer.exe b/entorno/Scripts/normalizer.exe new file mode 100644 index 0000000..29982ec Binary files /dev/null and b/entorno/Scripts/normalizer.exe differ diff --git a/entorno/Scripts/pip.exe b/entorno/Scripts/pip.exe new file mode 100644 index 0000000..08d7b6b Binary files /dev/null and b/entorno/Scripts/pip.exe differ diff --git a/entorno/Scripts/pip3.12.exe b/entorno/Scripts/pip3.12.exe new file mode 100644 index 0000000..08d7b6b Binary files /dev/null and b/entorno/Scripts/pip3.12.exe differ diff --git a/entorno/Scripts/pip3.exe b/entorno/Scripts/pip3.exe new file mode 100644 index 0000000..08d7b6b Binary files /dev/null and b/entorno/Scripts/pip3.exe differ diff --git a/entorno/Scripts/pyrsa-decrypt.exe b/entorno/Scripts/pyrsa-decrypt.exe new file mode 100644 index 0000000..340d43f Binary files /dev/null and b/entorno/Scripts/pyrsa-decrypt.exe differ diff --git a/entorno/Scripts/pyrsa-encrypt.exe b/entorno/Scripts/pyrsa-encrypt.exe new file mode 100644 index 0000000..3e6ed2c Binary files /dev/null and b/entorno/Scripts/pyrsa-encrypt.exe differ diff --git a/entorno/Scripts/pyrsa-keygen.exe b/entorno/Scripts/pyrsa-keygen.exe new file mode 100644 index 0000000..bb4eacb Binary files /dev/null and b/entorno/Scripts/pyrsa-keygen.exe differ diff --git a/entorno/Scripts/pyrsa-priv2pub.exe b/entorno/Scripts/pyrsa-priv2pub.exe new file mode 100644 index 0000000..3c36e3a Binary files /dev/null and b/entorno/Scripts/pyrsa-priv2pub.exe differ diff --git a/entorno/Scripts/pyrsa-sign.exe b/entorno/Scripts/pyrsa-sign.exe new file mode 100644 index 0000000..61596ed Binary files /dev/null and b/entorno/Scripts/pyrsa-sign.exe differ diff --git a/entorno/Scripts/pyrsa-verify.exe b/entorno/Scripts/pyrsa-verify.exe new file mode 100644 index 0000000..601e2fc Binary files /dev/null and b/entorno/Scripts/pyrsa-verify.exe differ diff --git a/entorno/Scripts/python.exe b/entorno/Scripts/python.exe new file mode 100644 index 0000000..ba0cd04 Binary files /dev/null and b/entorno/Scripts/python.exe differ diff --git a/entorno/Scripts/pythonw.exe b/entorno/Scripts/pythonw.exe new file mode 100644 index 0000000..68b3cfe Binary files /dev/null and b/entorno/Scripts/pythonw.exe differ diff --git a/entorno/Scripts/tqdm.exe b/entorno/Scripts/tqdm.exe new file mode 100644 index 0000000..c743393 Binary files /dev/null and b/entorno/Scripts/tqdm.exe differ diff --git a/entorno/pyvenv.cfg b/entorno/pyvenv.cfg new file mode 100644 index 0000000..8cee43a --- /dev/null +++ b/entorno/pyvenv.cfg @@ -0,0 +1,5 @@ +home = C:\Users\DELL13\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0 +include-system-site-packages = false +version = 3.12.10 +executable = C:\Users\DELL13\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe +command = C:\Users\DELL13\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe -m venv C:\Users\DELL13\Desktop\CURSO CHATBOT CON PYTHON\CLASES DE ESTE CURSO\python_telebots\entorno diff --git a/proyecto/Wendy_Moreno/Wendy_Moreno.py b/proyecto/Wendy_Moreno/Wendy_Moreno.py new file mode 100644 index 0000000..1b510fa --- /dev/null +++ b/proyecto/Wendy_Moreno/Wendy_Moreno.py @@ -0,0 +1,135 @@ +import os +import smtplib +from email.message import EmailMessage + +import openpyxl +from telebot import TeleBot, types + +# Configuración +TOKEN_BOT = '8130338428:AAFepXJ--dhup-dbLMpp_2ufU_kSwo48mJ8' +bot = TeleBot(TOKEN_BOT) + +SMTP_SERVER = 'smtp.gmail.com' +SMTP_PORT = 587 +SMTP_USER = 'wendymorenoc2024@gmail.com' +SMTP_PASSWORD = 'qwwcjnppcclzzrwh' +DESTINATARIO = 'wendymorenoc2024@gmail.com' + +EXCEL_FILE = 'mensajes_asesor.xlsx' + +# Crear archivo Excel si no existe +def crear_archivo_excel(): + if not os.path.exists(EXCEL_FILE): + wb = openpyxl.Workbook() + ws = wb.active + ws.title = "Mensajes" + ws.append(["Cédula/RUC", "Nombre", "Teléfono", "Mensaje"]) + wb.save(EXCEL_FILE) + +crear_archivo_excel() + +# Estado de usuarios +estado_usuario = {} +datos_usuario = {} + +@bot.message_handler(commands=['start']) +def start(message): + texto = "👋 *Bienvenido a Tributa Bien*\n\n¿En qué te puedo ayudar hoy?" + opciones = [ + "1️⃣ Apertura de RUC", + "2️⃣ Declaración de IVA", + "3️⃣ Declaración de RENTA", + "4️⃣ Patente Municipal Quito", + "5️⃣ Contactar a un Asesor" + ] + markup = types.ReplyKeyboardMarkup(resize_keyboard=True) + for opcion in opciones: + markup.add(opcion) + bot.send_message(message.chat.id, texto, parse_mode="Markdown", reply_markup=markup) + +@bot.message_handler(func=lambda msg: True) +def manejar_mensajes(message): + chat_id = message.chat.id + texto = message.text + + if chat_id in estado_usuario: + paso = estado_usuario[chat_id] + if paso == "cedula": + datos_usuario[chat_id]["cedula"] = texto + estado_usuario[chat_id] = "nombre" + bot.send_message(chat_id, "📛 Escribe tu *nombre completo*:", parse_mode="Markdown") + elif paso == "nombre": + datos_usuario[chat_id]["nombre"] = texto + estado_usuario[chat_id] = "telefono" + bot.send_message(chat_id, "📱 Escribe tu *número de teléfono*:", parse_mode="Markdown") + elif paso == "telefono": + datos_usuario[chat_id]["telefono"] = texto + estado_usuario[chat_id] = "mensaje" + bot.send_message(chat_id, "📝 Escribe tu *mensaje* de consulta:", parse_mode="Markdown") + elif paso == "mensaje": + datos_usuario[chat_id]["mensaje"] = texto + guardar_excel(datos_usuario[chat_id]) + enviar_email(datos_usuario[chat_id]) + bot.send_message(chat_id, "✅ ¡Mensaje enviado correctamente en breve un Asesor se comunicará contigo!") + del estado_usuario[chat_id] + del datos_usuario[chat_id] + return + + if texto.startswith("1️⃣"): + bot.send_message(chat_id, "📌 *Apertura de RUC*\n\nEn línea:\n- Firma electrónica\n- Cédula vigente\n- Factura de luz y agua\n- Correo electrónico\n- Monto de ventas\n- Actividad económica\n💵 Valor: 10 USD\n\nPresencial:\n- Autorización física firmada\n- Cédula\n- Dirección\n💵 Valor: 20 USD", parse_mode="Markdown") + elif texto.startswith("2️⃣"): + bot.send_message(chat_id, "📄 *Declaración de IVA*\n\n- Usuario y clave del SRI\n- Facturas de compras y ventas\n💵 Valor: según facturación", parse_mode="Markdown") + elif texto.startswith("3️⃣"): + bot.send_message(chat_id, "💰 *Declaración de RENTA*\n\n- Usuario y clave del SRI\n- Régimen y facturación\n💵 Valor: 20 USD", parse_mode="Markdown") + elif texto.startswith("4️⃣"): + bot.send_message(chat_id, "🏢 *Patente Municipal Quito*\n\n- Usuario y clave\n- Firma electrónica si aplica\n💵 Valor: 5 a 10 USD", parse_mode="Markdown") + elif texto.startswith("5️⃣"): + bot.send_message(chat_id, "📞 *Contactar a un Asesor*\n\nPor favor ingresa tu *cédula o RUC* para iniciar:", parse_mode="Markdown") + estado_usuario[chat_id] = "cedula" + datos_usuario[chat_id] = {} + else: + bot.send_message(chat_id, "❗ Usa el menú para elegir una opción válida.") + +def guardar_excel(datos): + try: + crear_archivo_excel() + wb = openpyxl.load_workbook(EXCEL_FILE) + ws = wb.active + ws.append([ + datos['cedula'], + datos['nombre'], + datos['telefono'], + datos['mensaje'] + ]) + wb.save(EXCEL_FILE) + print("✅ Mensaje guardado en Excel.") + except Exception as e: + print(f"❌ Error al guardar en Excel: {e}") + +def enviar_email(datos): + try: + msg = EmailMessage() + msg['Subject'] = f"Nuevo mensaje de {datos['nombre']} - {datos['cedula']}" + msg['From'] = SMTP_USER + msg['To'] = DESTINATARIO + + cuerpo = ( + f"Cédula o RUC: {datos['cedula']}\n" + f"Nombre: {datos['nombre']}\n" + f"Teléfono: {datos['telefono']}\n" + f"Mensaje:\n{datos['mensaje']}\n\n" + f"✅ Autorización para uso de datos otorgada por el usuario." + ) + msg.set_content(cuerpo) + + with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server: + server.starttls() + server.login(SMTP_USER, SMTP_PASSWORD) + server.send_message(msg) + print("📧 Correo enviado con éxito, en breve el Asesor se pondrá en contacto contigo.") + except Exception as e: + print(f"❌ Error al enviar correo: {e}") + +if __name__ == '__main__': + print("🤖 Bot ejecutándose...") + bot.infinity_polling() diff --git a/proyecto/Wendy_Moreno/mensajes.csv b/proyecto/Wendy_Moreno/mensajes.csv new file mode 100644 index 0000000..691869c --- /dev/null +++ b/proyecto/Wendy_Moreno/mensajes.csv @@ -0,0 +1,2 @@ +Cedula,Nombre,Telefono,Mensaje +1714653472,Wendy Moreno,0983894502,Quiero mas informacion diff --git a/proyecto/Wendy_Moreno/mensajes_asesor.xlsx b/proyecto/Wendy_Moreno/mensajes_asesor.xlsx new file mode 100644 index 0000000..9c16c8d Binary files /dev/null and b/proyecto/Wendy_Moreno/mensajes_asesor.xlsx differ diff --git a/proyecto/edisontana/README.md b/proyecto/edisontana/README.md new file mode 100644 index 0000000..6a953f4 --- /dev/null +++ b/proyecto/edisontana/README.md @@ -0,0 +1,20 @@ + +--- + +# Proyecto del bot en telegram + +Por Edison TANA +Archivo: mitelegrambotTopograf.py + +## Licencia + +[![CC BY-SA 4.0][cc-by-sa-shield]][cc-by-sa] + +Este trabajo está licenciado bajo +[Creative Commons Attribution-ShareAlike 4.0 International License][cc-by-sa] y GNU GPL v3 + +[![CC BY-SA 4.0][cc-by-sa-image]][cc-by-sa] + +[cc-by-sa]: http://creativecommons.org/licenses/by-sa/4.0/ +[cc-by-sa-image]: https://licensebuttons.net/l/by-sa/4.0/88x31.png +[cc-by-sa-shield]: https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg \ No newline at end of file diff --git a/proyecto/edisontana/proyectobot/mitelegrambotTopograf.py b/proyecto/edisontana/proyectobot/mitelegrambotTopograf.py new file mode 100644 index 0000000..e6ecf94 --- /dev/null +++ b/proyecto/edisontana/proyectobot/mitelegrambotTopograf.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# mitelegrambotTopograf.py +# +# Copyright 2025 Edison TANA +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# Desarrollado en GNU_Linux + + +from telegram import Update, ReplyKeyboardMarkup +from telegram.ext import ( + ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, + filters, ConversationHandler +) +from mailjet_rest import Client +import requests +import os +import re +import sqlite3 +import logging +from datetime import datetime +from dotenv import load_dotenv + +load_dotenv() + +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +api_key = os.getenv('MAILJET_API_KEY') +api_secret = os.getenv('MAILJET_SECRET_KEY') + +correoremite = os.getenv('EMAIL_REMITENTE') +correodestino = os.getenv('EMAIL_DESTINATARIO') + + +MAIN_MENU, FIRST_MENU, SECOND_MENU, THIRD_MENU = range(4) + +SERVICIOS = { + "1. 🗺️ Modelos de terreno en 3D": 100, + "2. 📏 Nivelaciones y replanteos": 12, + "3. 🌎 Levantamientos topograficos": 180, + "4. 👨 Asesoría topografica": 60 +} + +conn = sqlite3.connect("mibase.db", check_same_thread=False) +cursor = conn.cursor() + +cursor.execute(""" +CREATE TABLE IF NOT EXISTS chat_data ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + username TEXT, + servicio TEXT, + message_id INTEGER, + timestamp TEXT +) +""") +conn.commit() + +def guardar_interaccion(update: Update): + user = update.effective_user + username = user.username or "Sin username" + message_id = update.message.message_id + servicio = update.message.text + timestamp = datetime.now().isoformat() + + cursor.execute(""" + INSERT INTO chat_data (user_id, message_id, username, servicio, timestamp) + VALUES (?, ?, ?, ?, ?) + """, (user.id, username, servicio, message_id, timestamp)) + conn.commit() + +# Extraer correo desde un texto +def extraer_email(texto): + match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', texto) + return match.group(0) if match else None + +def enviarcorreos(context, correodestino, asunto, contenido): + + mailjet = Client(auth=(api_key, api_secret), version='v3.1') + data = { + 'Messages': [ + { + "From": { + "Email": correoremite, # Remove $ and use variable directly + "Name": "Info EuatorTopografia" + }, + "To": [ + { + "Email": correodestino, # Remove $ and use variable directly + "Name": "Cliente de equatortopografia " + } + ], + "Subject": asunto, + "TextPart": "Saludos desde Topografia!", + "HTMLPart": f""" +

Estimado usuario, bienvenido a EquatorTopografia!


Un gusto conectar con usted! +
+

Usted ha elegido el servicio de:

+
    +
  • +

    {context.user_data['servicio']}

    +
  • +
  • Su detalle es {context.user_data['datos']}
  • +
  • Su costo es ${SERVICIOS[context.user_data['servicio']]}
  • +
+
+ Gracias por escribirnos, hasta pronto. +
+

Más servicios

+
+
    +
  1. Modelos de terreno en 3D
  2. +
  3. Levantamientos topograficos
  4. +
  5. +

    Nivelaciones y replanteos con precision topografica

    +
  6. +
  7. +

    Georeferenciaciones

    +
  8. +
  9. +

    Digitalización topografica

    +
  10. +
+
+
+

Contacta por telegram con nuestro asesor en t.me/leosAcadUIO

+ """ + } + ] + } + + result = mailjet.send.create(data=data) + print(result.status_code) + print('Ok') + + +# Inicio del bot +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + mensaje = ( + """ + Hola. Buen día \n 🌟 Bienvenido/a a AsistenteBot! (@academicobot) 🌟.\n + ______________________________________ + < Te ayudamos en soporte y asesoría de > + ----------------------------------------------------------------------- + + A continuacion elige un ítem de la lista: + """ + ) + keyboard = [[opcion] for opcion in SERVICIOS.keys()] + await update.message.reply_text( + mensaje, + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + guardar_interaccion(update) + return MAIN_MENU + +# Selección del servicio +async def seleccionar_servicio(update: Update, context: ContextTypes.DEFAULT_TYPE): + servicio = update.message.text.strip() + if servicio in SERVICIOS: + context.user_data["servicio"] = servicio + await update.message.reply_text( + f"📝 Has seleccionado *{servicio}*.\n\nPor favor, digita su:\n1. Nombre completo\n2. Correo electrónico\n3. Una breve detalle de su caso:", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return FIRST_MENU + else: + await update.message.reply_text("Opción inválida. Selecciona un servicio del menú.") + return await start(update, context) + + +# Recolección de datos +async def recibir_datos(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.strip() + email = extraer_email(texto) + if not email: + await update.message.reply_text( + "Se encontró un error.\n De nuevo ingrese su informacion de acuerdo a este formato:\n\n`Nombre - correo@ejemplo.com - detalle`", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return FIRST_MENU + + context.user_data["datos"] = texto + keyboard = [["Sí", "No"]] + await update.message.reply_text( + " Autorizo a EquatorTopografia a verificar la autenticidad de la información proporcionada y utilizarla para fines informativos. Entiendo que mis datos serán tratados conforme a la Ley de Protección de Datos Personales de EC.: \n SI / NO", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True) + ) + guardar_interaccion(update) + return SECOND_MENU + +async def autorizacion(update: Update, context: ContextTypes.DEFAULT_TYPE): + respuesta = update.message.text.lower() + # Fix: Remove redundant 'in respuesta' checks + if "si" in respuesta or "sí" in respuesta: + servicio = context.user_data["servicio"] + precio = SERVICIOS[servicio] + keyboard = [["✅ Confirmar", "❌ Cancelar"]] + await update.message.reply_text( + f"El *{servicio}* tiene un costo de *${precio}*.\n\n¿Deseas confirmar el pedido?\n Confirmar / Cancelar", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + guardar_interaccion(update) + return THIRD_MENU + elif "no" in respuesta: + await update.message.reply_text("No podemos continuar sin tu autorización. Escribe /start para comenzar de nuevo.") + return ConversationHandler.END + else: + await update.message.reply_text("Respuesta inválida. Selecciona *Sí* o *No* desde el menú.") + return SECOND_MENU + +async def confirmar(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.lower() + guardar_interaccion(update) + # A + if "confirmar" in texto: + servicio = context.user_data["servicio"] + detalle = context.user_data["datos"] + precio = SERVICIOS[servicio] + correo = extraer_email(detalle) + correodestinos = correo + + mensaje = ( + f"*Gracias por tu pedido!*\n\n" + f"*Servicio:* {servicio}\n" + f"*Detalle:* {detalle}\n" + f"*Precio:* ${precio}\n\n" + "Nos pondremos en contacto contigo pronto. 📧" + ) + + # Optional: Add logging instead of print statements + logging.info(f"Email: {detalle}, Precio: {precio}, Correo: {correo}") + logging.info(f"Mensaje: {mensaje}") + + if correo: + try: + enviado = enviarcorreos(context, correodestinos, ":) Info sobre cotizacion para "+correo, mensaje) + await update.message.reply_text("Correo enviado exitosamente.") + except Exception as e: + logging.error(f"Error enviando correo: {e}") + await update.message.reply_text("Hubo un problema al enviar el correo.") + else: + await update.message.reply_text("Correo NO enviado") + + await update.message.reply_text("¿Requieres cotizarotro servicio? Digita /start para volver al menú principal") + return ConversationHandler.END + elif "cancelar" in texto or texto == "❌": + await update.message.reply_text("Servicio cancelado. Si deseas iniciar de nuevo, escribe /start.") + return ConversationHandler.END + else: + await update.message.reply_text("Respuesta inválida. Selecciona *Confirmar* o *Cancelar* desde el menú.") + return THIRD_MENU # Fix: Return to THIRD_MENU instead of MAIN_MENU + + + +# Mi funcion pincipal +def main(): + app = ApplicationBuilder().token(BOT_TOKEN).build() + + conv_handler = ConversationHandler( + entry_points=[CommandHandler("start", start)], + states={ + MAIN_MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, seleccionar_servicio)], + FIRST_MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, recibir_datos)], + SECOND_MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, autorizacion)], + THIRD_MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, confirmar)], + }, + fallbacks=[], + ) + + app.add_handler(conv_handler) + print("mi bot ejecutandose") + app.run_polling() + +if __name__ == "__main__": + main() diff --git a/proyecto/geomara_maribel_tambaco_tipantiza/app.py b/proyecto/geomara_maribel_tambaco_tipantiza/app.py new file mode 100644 index 0000000..3a4a9ef --- /dev/null +++ b/proyecto/geomara_maribel_tambaco_tipantiza/app.py @@ -0,0 +1,222 @@ +from telegram import Update, ReplyKeyboardMarkup +from telegram.ext import ( + ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, + filters, ConversationHandler +) +import sqlite3 +import os +import re +import requests +from datetime import datetime +from dotenv import load_dotenv + +load_dotenv() + +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +MAILJET_API_KEY = os.getenv("MAILJET_API_KEY") +MAILJET_SECRET_KEY = os.getenv("MAILJET_SECRET_KEY") +MAILJET_URL = os.getenv("MAILJET_URL") +MAILJET_FROM_NAME = os.getenv("MAILJET_FROM_NAME") +EMAIL_FROM = os.getenv("EMAIL_FROM") + +MENU, DATOS, AUTORIZACION, CONFIRMAR = range(4) + +# Cursos de capacitación que ofrece KonKito +CURSOS = { + "1. 📈 Marketing Digital para Emprendedores": 300, + "2. 💼 Gestión Financiera Básica": 250, + "3. 🚀 Estrategias de Crecimiento": 350, + "4. 🛠️ Herramientas para la Productividad": 200 +} + +conn = sqlite3.connect("chat.db", check_same_thread=False) +cursor = conn.cursor() +cursor.execute(""" +CREATE TABLE IF NOT EXISTS chat_data ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + username TEXT, + curso TEXT, + message_id INTEGER, + timestamp TEXT +) +""") +conn.commit() + +def guardar_interaccion(update: Update): + user = update.effective_user + username = user.username or "Sin username" + texto = update.message.text + message_id = update.message.message_id + timestamp = datetime.now().isoformat() + + cursor.execute(""" + INSERT INTO chat_data (user_id, username, curso, message_id, timestamp) + VALUES (?, ?, ?, ?, ?) + """, (user.id, username, texto, message_id, timestamp)) + conn.commit() + +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + mensaje = ( + "🚀 Bienvenido al *Bot de Cursos de capacitación de KonKito*.\n\n" + "Selecciona un curso para continuar:" + ) + keyboard = [[curso] for curso in CURSOS.keys()] + await update.message.reply_text( + mensaje, + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + guardar_interaccion(update) + return MENU + +async def seleccionar_curso(update: Update, context: ContextTypes.DEFAULT_TYPE): + curso = update.message.text.strip() + if curso in CURSOS: + context.user_data["curso"] = curso + await update.message.reply_text( + "✍️ Por favor, escribe:\n1. Tu nombre completo\n2. Tu correo electrónico\n3. Una breve descripción de tu emprendimiento\n\nFormato:\n`Vilma Pérez - correo@ejemplo.com - Información de . . .`", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return DATOS + else: + await update.message.reply_text("❌ Opción inválida. Usa el menú para elegir un curso.") + return MENU + +async def recibir_datos(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.strip() + email = extraer_email(texto) + if not email: + await update.message.reply_text( + "❌ No se detectó un correo válido. Escribe tus datos así:\n`Nombre - correo@ejemplo.com - descripción`", + parse_mode="Markdown" + ) + return DATOS + + context.user_data["datos"] = texto + keyboard = [["✅ Sí", "❌ No"]] + await update.message.reply_text( + "🔐 ¿Autorizas el uso de tus datos para contactarte y procesar tu inscripción?", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True) + ) + guardar_interaccion(update) + return AUTORIZACION + +async def autorizacion(update: Update, context: ContextTypes.DEFAULT_TYPE): + respuesta = update.message.text.lower() + if "sí" in respuesta or "si" in respuesta or "✅" in respuesta: + curso = context.user_data["curso"] + precio = CURSOS[curso] + keyboard = [["✅ Confirmar", "❌ Cancelar"]] + await update.message.reply_text( + f"💰 El precio del curso *{curso}* es de *${precio}*.\n¿Deseas confirmar tu inscripción?", + reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True), + parse_mode="Markdown" + ) + return CONFIRMAR + elif "no" in respuesta or "❌" in respuesta: + await update.message.reply_text("🚫 No podemos continuar sin tu autorización. Escribe /start para reiniciar.") + return ConversationHandler.END + else: + await update.message.reply_text("❌ Respuesta no válida. Usa el menú.") + return AUTORIZACION + +async def confirmar(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.lower() + if "confirmar" in texto or "✅" in texto: + curso = context.user_data["curso"] + descripcion = context.user_data["datos"] + correo = extraer_email(descripcion) + + mensaje = ( + f"🎉 *Gracias por inscribirte!*\n\n" + f"✅ *Curso:* {curso}\n" + f"📝 *Descripción:* {descripcion}\n" + f"💵 *Precio:* ${CURSOS[curso]}\n\n" + "Nos pondremos en contacto contigo pronto. 📧" + ) + + enviado = enviar_mailjet(context, correo, "Confirmación de inscripción", mensaje) + if enviado: + await update.message.reply_text("📧 Correo de confirmación enviado con éxito.") + else: + await update.message.reply_text("⚠️ Hubo un error al enviar el correo.") + + await update.message.reply_text("¿Necesitas algo más? Escribe /start para comenzar otra inscripción.") + return ConversationHandler.END + + elif "cancelar" in texto or "❌" in texto: + await update.message.reply_text("❌ Inscripción cancelada. Escribe /start para iniciar de nuevo.") + return ConversationHandler.END + + else: + await update.message.reply_text("❌ Respuesta inválida. Usa el menú.") + return CONFIRMAR + +def extraer_email(texto): + match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', texto) + return match.group(0) if match else None + +def enviar_mailjet(context, destinatario, asunto, contenido): + data = { + "Messages": [ + { + "From": { + "Email": EMAIL_FROM, + "Name": MAILJET_FROM_NAME + }, + "To": [ + { + "Email": destinatario, + "Name": "Cliente" + } + ], + "Subject": asunto, + "HTMLPart": f""" +
+

🎉 ¡Gracias por tu inscripción!

+

Curso: {context.user_data['curso']}

+

📝 Descripción: {context.user_data['datos']}

+

💵 Precio: ${CURSOS[context.user_data['curso']]}

+

Nos pondremos en contacto contigo pronto.

+
+ """ + } + ] + } + + try: + response = requests.post( + MAILJET_URL, + json=data, + auth=(MAILJET_API_KEY, MAILJET_SECRET_KEY), + timeout=(3.05, 5) + ) + print(f"Mailjet response: {response.status_code} - {response.text}") + return response.status_code == 200 + except Exception as e: + print(f"Error enviando correo con Mailjet: {e}") + return False + +def main(): + app = ApplicationBuilder().token(BOT_TOKEN).build() + + conv_handler = ConversationHandler( + entry_points=[CommandHandler("start", start)], + states={ + MENU: [MessageHandler(filters.TEXT & ~filters.COMMAND, seleccionar_curso)], + DATOS: [MessageHandler(filters.TEXT & ~filters.COMMAND, recibir_datos)], + AUTORIZACION: [MessageHandler(filters.TEXT & ~filters.COMMAND, autorizacion)], + CONFIRMAR: [MessageHandler(filters.TEXT & ~filters.COMMAND, confirmar)], + }, + fallbacks=[], + ) + + app.add_handler(conv_handler) + + print("🤖 Bot en ejecución...") + app.run_polling() + +if __name__ == "__main__": + main() diff --git a/proyecto/geomara_maribel_tambaco_tipantiza/chat.db b/proyecto/geomara_maribel_tambaco_tipantiza/chat.db new file mode 100644 index 0000000..f51beba Binary files /dev/null and b/proyecto/geomara_maribel_tambaco_tipantiza/chat.db differ diff --git a/proyecto/geomara_maribel_tambaco_tipantiza/ver_datos.py b/proyecto/geomara_maribel_tambaco_tipantiza/ver_datos.py new file mode 100644 index 0000000..14afec9 --- /dev/null +++ b/proyecto/geomara_maribel_tambaco_tipantiza/ver_datos.py @@ -0,0 +1,12 @@ +import sqlite3 + +conn = sqlite3.connect("chat.db") +cursor = conn.cursor() + +cursor.execute("SELECT * FROM chat_data") +rows = cursor.fetchall() + +for row in rows: + print(row) + +conn.close() diff --git a/proyecto/jorge_guato/app.py b/proyecto/jorge_guato/app.py new file mode 100644 index 0000000..268e62d --- /dev/null +++ b/proyecto/jorge_guato/app.py @@ -0,0 +1,178 @@ +import telebot +from telebot.types import ReplyKeyboardMarkup, KeyboardButton, Message +import sqlite3 +import json +import os +from dotenv import load_dotenv + +# Cargar variables de entorno +load_dotenv() +BOT_TOKEN = os.getenv("BOT_TOKEN") + +# Inicializar bot +bot = telebot.TeleBot(BOT_TOKEN) + +# --- Clases --- +class DBHelper: + @staticmethod + def init(): + with sqlite3.connect("chat.db") as conn: + c = conn.cursor() + c.execute(''' + CREATE TABLE IF NOT EXISTS pedidos ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + nombre TEXT, + telefono TEXT, + email TEXT, + direccion TEXT, + productos TEXT, + total REAL, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP + ) + ''') + + @staticmethod + def guardar_pedido(user_id, datos): + with sqlite3.connect("chat.db") as conn: + c = conn.cursor() + c.execute(''' + INSERT INTO pedidos (user_id, nombre, telefono, email, direccion, productos, total) + VALUES (?, ?, ?, ?, ?, ?, ?) + ''', ( + user_id, + datos["nombre"], + datos["telefono"], + datos["email"], + datos["direccion"], + json.dumps(datos["productos"]), + datos["total"] + )) + +class PedidoManager: + ESTADOS = { + "MENU": "menu", + "PEDIDO_NOMBRE": "nombre", + "PEDIDO_TELEFONO": "telefono", + "PEDIDO_EMAIL": "email", + "PEDIDO_DIRECCION": "direccion" + } + + PRODUCTOS = { + "1": {"nombre": "Vino de Uva Premium", "precio": 25.00}, + "2": {"nombre": "Vino de Mortiño", "precio": 30.00}, + "3": {"nombre": "Vino de Arándano", "precio": 28.00}, + "4": {"nombre": "Chocolate Clásico", "precio": 8.00}, + "5": {"nombre": "Chocolate Premium", "precio": 12.00}, + "6": {"nombre": "Chocolate Especial", "precio": 15.00} + } + + usuarios = {} + + @classmethod + def reiniciar(cls, user_id): + cls.usuarios[user_id] = {"estado": cls.ESTADOS["MENU"], "carrito": []} + + @classmethod + def agregar_producto(cls, user_id, codigo): + producto = cls.PRODUCTOS.get(codigo) + if producto: + cls.usuarios[user_id]["carrito"].append(producto) + total = sum(p["precio"] for p in cls.usuarios[user_id]["carrito"]) + cls.usuarios[user_id]["pedido"] = {"productos": cls.usuarios[user_id]["carrito"], "total": total} + cls.usuarios[user_id]["estado"] = cls.ESTADOS["PEDIDO_NOMBRE"] + bot.send_message(user_id, f"🛒 {producto['nombre']} añadido al carrito.") + bot.send_message(user_id, "👤 Ingresa tu nombre completo o escribe 0 para salir:") + else: + bot.send_message(user_id, "Producto no válido.") + +# --- Bot Handlers --- +@bot.message_handler(commands=["start"]) +def start(message: Message): + user_id = message.from_user.id + PedidoManager.reiniciar(user_id) + + markup = ReplyKeyboardMarkup(resize_keyboard=True) + markup.add("1. Ver Catálogo de Vinos", "2. Ver Catálogo de Chocolates", "0. Salir") + + texto = """ +👋 *¡Hola! Bienvenido a La Rústica* 🍷🍫 + +1. Ver Catálogo de Vinos +2. Ver Catálogo de Chocolates +0. Salir + +Elige una opción: + """ + bot.send_message(user_id, texto, reply_markup=markup, parse_mode="Markdown") + +def mostrar_catalogo_vinos(user_id): + texto = "🍷 *Catálogo de Vinos*\n" + texto += "1. Vino de Uva Premium - $25.00\n" + texto += "2. Vino de Mortiño - $30.00\n" + texto += "3. Vino de Arándano - $28.00\n" + texto += "\nEscribe el número del producto para seleccionarlo, o 0 para salir." + bot.send_message(user_id, texto, parse_mode="Markdown") + +def mostrar_catalogo_chocolates(user_id): + texto = "🍫 *Chocolates La Rústica*\n" + texto += "4. Chocolate Clásico - $8.00\n" + texto += "5. Chocolate Premium - $12.00\n" + texto += "6. Chocolate Especial - $15.00\n" + texto += "\nEscribe el número del producto para seleccionarlo, o 0 para salir." + bot.send_message(user_id, texto, parse_mode="Markdown") + +@bot.message_handler(func=lambda m: True) +def handle_message(message: Message): + user_id = message.from_user.id + texto = message.text.strip() + + if user_id not in PedidoManager.usuarios: + PedidoManager.reiniciar(user_id) + + if texto == "0": + PedidoManager.reiniciar(user_id) + bot.send_message(user_id, "❌ Proceso cancelado.") + return start(message) + + estado = PedidoManager.usuarios[user_id]["estado"] + + if estado == PedidoManager.ESTADOS["MENU"]: + if texto == "1. Ver Catálogo de Vinos": + mostrar_catalogo_vinos(user_id) + elif texto == "2. Ver Catálogo de Chocolates": + mostrar_catalogo_chocolates(user_id) + elif texto in PedidoManager.PRODUCTOS: + PedidoManager.agregar_producto(user_id, texto) + else: + bot.send_message(user_id, "Por favor, selecciona una opción del menú.") + + elif estado == PedidoManager.ESTADOS["PEDIDO_NOMBRE"]: + PedidoManager.usuarios[user_id]["pedido"]["nombre"] = texto + PedidoManager.usuarios[user_id]["estado"] = PedidoManager.ESTADOS["PEDIDO_TELEFONO"] + bot.send_message(user_id, "📞 Ingresa tu teléfono o escribe 0 para salir:") + + elif estado == PedidoManager.ESTADOS["PEDIDO_TELEFONO"]: + PedidoManager.usuarios[user_id]["pedido"]["telefono"] = texto + PedidoManager.usuarios[user_id]["estado"] = PedidoManager.ESTADOS["PEDIDO_EMAIL"] + bot.send_message(user_id, "📧 Ingresa tu email o escribe 0 para salir:") + + elif estado == PedidoManager.ESTADOS["PEDIDO_EMAIL"]: + PedidoManager.usuarios[user_id]["pedido"]["email"] = texto + PedidoManager.usuarios[user_id]["estado"] = PedidoManager.ESTADOS["PEDIDO_DIRECCION"] + bot.send_message(user_id, "📍 Ingresa tu dirección o escribe 0 para salir:") + + elif estado == PedidoManager.ESTADOS["PEDIDO_DIRECCION"]: + PedidoManager.usuarios[user_id]["pedido"]["direccion"] = texto + DBHelper.guardar_pedido(user_id, PedidoManager.usuarios[user_id]["pedido"]) + bot.send_message(user_id, "✅ Pedido guardado correctamente. Te contactaremos pronto. 🎉") + PedidoManager.reiniciar(user_id) + start(message) + else: + bot.send_message(user_id, "Usa el menú para continuar.") + +# Iniciar bot +if __name__ == "__main__": + DBHelper.init() + print("🤖 Bot iniciado...") + bot.infinity_polling() diff --git a/proyecto/jorge_guato/chat.db b/proyecto/jorge_guato/chat.db new file mode 100644 index 0000000..d63dbe2 Binary files /dev/null and b/proyecto/jorge_guato/chat.db differ diff --git a/proyecto/jorge_guato/readme.md b/proyecto/jorge_guato/readme.md new file mode 100644 index 0000000..6d7f27d --- /dev/null +++ b/proyecto/jorge_guato/readme.md @@ -0,0 +1,12 @@ +# Bot de Telegram - La Rustica + +Este proyecto implementa un chatbot en Telegram para una empresa de vinos y chocolates. + +## Funcionalidades + +- Saludo personalizado +- Menú interactivo con productos: + - Vinos de uva, mortiño y arándano + - Chocolates "La Rustica" +- Solicita cantidad y nombre del cliente +- Almacena los pedidos en una base de datos SQLite (`chat.db`) \ No newline at end of file diff --git a/proyecto/jorge_luis_castellanos/app.py b/proyecto/jorge_luis_castellanos/app.py new file mode 100644 index 0000000..30ac87c --- /dev/null +++ b/proyecto/jorge_luis_castellanos/app.py @@ -0,0 +1,59 @@ +from telegram import Update, ReplyKeyboardMarkup +from telegram.ext import ( + ApplicationBuilder, CommandHandler, MessageHandler, ContextTypes, + filters, ConversationHandler +) +from mailjet_rest import Client +import requests +import os +import re +import sqlite3 +from datetime import datetime +from dotenv import load_dotenv +from telebot import TeleBot, types +import datetime + +load_dotenv() + +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +bot = TeleBot(BOT_TOKEN) + +# Estado temporal de los usuarios +user_data = {} + +@bot.message_handler(commands=['start']) +def start(message): + bot.send_message(message.chat.id, "Hola...\nTe saluda Terra Habitat Bienes Raices\nPor favor, escribe tu nombre completo:") + bot.register_next_step_handler(message, process_nombre) + +def process_nombre(message): + user_data[message.chat.id] = {"nombre": message.text} + + bot.send_message(message.chat.id, "¿Qué servicio deseas? \n (Compra - Venta - Alquiler - Avalúo - Administración - Otro Servicio)") + bot.register_next_step_handler(message, process_servicio) + +def process_servicio(message): + user_data[message.chat.id]["servicio"] = message.text + + bot.send_message(message.chat.id, "Ayudame con tu número de teléfono") + bot.register_next_step_handler(message, process_telefono) + +def process_telefono(message): + user_data[message.chat.id]["telefono"] = message.text + + bot.send_message(message.chat.id, "Ayudame con tu correo electrónico") + bot.register_next_step_handler(message, cita) + +def cita(message): + user_data[message.chat.id]["time"] = message.text + data = user_data[message.chat.id] + + bot.send_message(message.chat.id, "🔹¡Tu cita ha sido registrada!\nUn Asesor te atendera de forma presonalizada") + resumen = f"🗓️*Resumen de tu cita:*\nNombre: {data['nombre']}\nServicio: {data['servicio']}\nTelefono: {data['telefono']}" + + bot.send_message(message.chat.id, resumen, parse_mode='Markdown') + + +if __name__ == "__main__": + print("Bot ejecutándose...") + bot.infinity_polling() \ No newline at end of file diff --git a/proyecto/jorge_luis_castellanos/readme.txt b/proyecto/jorge_luis_castellanos/readme.txt new file mode 100644 index 0000000..611d11c --- /dev/null +++ b/proyecto/jorge_luis_castellanos/readme.txt @@ -0,0 +1,5 @@ +Bot de Telegram + +Este bot crea una cita para contacto automatico con la Api de Telegram para la empresa de bienes raices Terra Habitat +Fue desarrollado con la libreria de Telebot y Telegram +Como caracteristicas futuras, se espera implementar el mismo bot con flask y posiblemente con Whatsapp ya que es el principal canal de comunicacion \ No newline at end of file diff --git a/proyecto/jorge_luis_castellanos/requirements.txt b/proyecto/jorge_luis_castellanos/requirements.txt new file mode 100644 index 0000000..7ce90bd --- /dev/null +++ b/proyecto/jorge_luis_castellanos/requirements.txt @@ -0,0 +1,24 @@ +anyio==4.9.0 +blinker==1.9.0 +certifi==2025.7.14 +charset-normalizer==3.4.2 +click==8.2.1 +Flask==3.1.1 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.10 +itsdangerous==2.2.0 +Jinja2==3.1.6 +mailjet-rest==1.5.1 +MarkupSafe==3.0.2 +pyTelegramBotAPI==4.27.0 +python-dotenv==1.1.1 +python-telegram-bot==22.2 +requests==2.32.4 +sniffio==1.3.1 +telebot==0.0.5 +telegram==0.0.1 +typing_extensions==4.14.1 +urllib3==2.5.0 +Werkzeug==3.1.3 diff --git a/proyecto/jorge_luis_castellanos/telebot_complete.db b/proyecto/jorge_luis_castellanos/telebot_complete.db new file mode 100644 index 0000000..f678dcb Binary files /dev/null and b/proyecto/jorge_luis_castellanos/telebot_complete.db differ diff --git a/proyecto/proyecto-carlos_bodero/app.py b/proyecto/proyecto-carlos_bodero/app.py new file mode 100644 index 0000000..ffea971 --- /dev/null +++ b/proyecto/proyecto-carlos_bodero/app.py @@ -0,0 +1,111 @@ +import os +import google.generativeai as genai +import smtplib +from email.message import EmailMessage +from flask import Flask, render_template, request, jsonify +from dotenv import load_dotenv +from sqlalchemy import create_engine, Column, Integer, String, Text +from sqlalchemy.orm import declarative_base, sessionmaker + +# Carga variables de entorno +load_dotenv() +GEMINI_API_KEY = os.getenv("API_KEY_GEMINI") +USUARIO_CORREO = os.getenv("USUARIO_CORREO") +CONTRASENA_CORREO = os.getenv("CONTRASENA_CORREO") + + +if not GEMINI_API_KEY: + raise Exception("La API Key de Gemini no está configurada en el archivo .env.") + + +modelo_en_uso = None + +modelos = [ + "gemini-2.5-flash", + "gemini-2.5-flash-latest", + "gemini-2.5-flash-002", + "gemini-2.5-pro", + "gemini-2.5-pro-latest", + "gemini-2.5-pro-002", + "gemini-1.5-flash", + "gemini-1.5-flash-latest", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-latest", + "gemini-1.5-pro-002", +] + +# Datos de tu cuenta Gmail +usuario_mail = USUARIO_CORREO +contrasena = CONTRASENA_CORREO + +genai.configure(api_key=GEMINI_API_KEY) +modelo_en_uso = modelos[0] + +# Flask y DB setup +app = Flask(__name__) +#DATABASE_URL = "sqlite:///chat.db" +DATABASE_URL = "sqlite:///proyecto/proyecto-carlos_bodero/chat.db" +engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) +Base = declarative_base() + +# Modelo de Chat +class Chat(Base): + __tablename__ = 'chat' + id = Column(Integer, primary_key=True) + usuario_nombre = Column(String(100)) + correo = Column(String(100)) + texto = Column(Text) + +Base.metadata.create_all(engine) +Session = sessionmaker(bind=engine) +db_session = Session() + +def consultar_gemini(mensaje): + model = genai.GenerativeModel(modelo_en_uso) + try: + response = model.generate_content(mensaje) + return response.text + except Exception as e: + return f"Error consultando Gemini: {str(e)}" + +def enviarCorreo(usuario,correo,mensaje): + # Configuración del mensaje + msg = EmailMessage() + msg['Subject'] = "Chat " + str(usuario) + msg['From'] = 'monitorcbo4@gmail.com' + msg['To'] = str(correo) + msg.set_content(mensaje) + try: + with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp: + smtp.login(usuario_mail, contrasena) + smtp.send_message(msg) + print("Correo enviado correctamente.") + except Exception as e: + print("Error al enviar el correo:", e) + +@app.route("/") +def index(): + return render_template("index.html") + +@app.route("/chat", methods=["POST"]) +def chat(): + data = request.json + user_message = data.get("message") + respuesta_gemini = consultar_gemini(user_message) + return jsonify({"response": respuesta_gemini}) + +@app.route("/guardar", methods=["POST"]) +def guardar(): + data = request.json + nombre = data.get("nombre") + correo = data.get("email") + texto_chat = data.get("chat") + chat_entry = Chat(usuario_nombre=nombre, correo=correo, texto=texto_chat) + db_session.add(chat_entry) + db_session.commit() + enviarCorreo(nombre,correo,texto_chat) + return jsonify({"status": "ok"}) + +if __name__ == "__main__": + app.run("0.0.0.0",debug=True) diff --git a/proyecto/proyecto-carlos_bodero/chat.db b/proyecto/proyecto-carlos_bodero/chat.db new file mode 100644 index 0000000..23973e5 Binary files /dev/null and b/proyecto/proyecto-carlos_bodero/chat.db differ diff --git a/proyecto/proyecto-carlos_bodero/readme.md b/proyecto/proyecto-carlos_bodero/readme.md new file mode 100644 index 0000000..091ce78 --- /dev/null +++ b/proyecto/proyecto-carlos_bodero/readme.md @@ -0,0 +1,95 @@ +# Chat Gemini con Flask y SQLite + +Este proyecto es una aplicación web de chat construida con **Flask** que permite interactuar con la IA de **Gemini** (Google). La aplicación almacena cada conversación en una base de datos **SQLite**, guardando el nombre, correo electrónico del usuario y el historial del chat. + +--- + +## Características + +- Interfaz web amigable para chatear con Gemini. +- Campos para ingresar **nombre** y **correo electrónico** del usuario. +- Al finalizar la conversación, se almacena todo el chat en SQLite. +- Integración con la API oficial de Gemini (`google-generativeai`). + +--- + +## Requisitos + +- Python 3.8 o superior +- Cuenta de Google para obtener la API Key de Gemini + +--- + +## Instalación + +1. **Clona este repositorio** o descarga el código. + +2. **Instala las dependencias**: + + ```bash + pip install flask google-generativeai python-dotenv sqlalchemy + ``` + +3. **Obtén tu API Key de Gemini**: + + - Accede a [Google AI Studio](https://aistudio.google.com/app/apikey) + - Inicia sesión con tu cuenta Google + - Haz clic en “Create API key” y copia el valor + +4. **Configuración archivo `.env`**: + + + ``` + API_KEY_GEMINI=api_key_de_gemini + USUARIO_MAIL= contraseña GMAIL + CONTRASENA_MAIL=contraseña de aplicacion GMAIL + ``` + +--- + +## Uso + +1. Ejecuta la aplicación: + + ```bash + python app.py + ``` + +2. Abre tu navegador en [http://127.0.0.1:5000](http://127.0.0.1:5000) + +3. Ingresa tu nombre y correo electrónico, chatea con Gemini y al finalizar haz clic en el botón **Limpiar** para guardar la conversación. + +4. Las conversaciones se almacenan en `chat.db` en la tabla `chat`. + +--- + +## Estructura de la base de datos + +Tabla: **chat** + +| Campo | Tipo | Descripción | +|-----------------|----------|---------------------------------------| +| id | Integer | Clave primaria (autoincremental) | +| usuario_nombre | String | Nombre del usuario | +| correo | String | Correo electrónico del usuario | +| texto | Text | Conversación completa (historial chat)| + + +--- + +## Seguridad + + +- Las variables de entorno globales en el archivo `.env` `.gitignore`. + +--- + +## Créditos + +Desarrollado por Carlos Bodero. + +--- + +## Licencia + +Este proyecto se proporciona bajo la licencia MIT. Puedes modificar y usar el código libremente. diff --git a/proyecto/proyecto-carlos_bodero/requirements.txt b/proyecto/proyecto-carlos_bodero/requirements.txt new file mode 100644 index 0000000..5eaf725 --- /dev/null +++ b/proyecto/proyecto-carlos_bodero/requirements.txt @@ -0,0 +1,2 @@ +flask +requests \ No newline at end of file diff --git a/proyecto/proyecto-carlos_bodero/templates/index.html b/proyecto/proyecto-carlos_bodero/templates/index.html new file mode 100644 index 0000000..8b42d3f --- /dev/null +++ b/proyecto/proyecto-carlos_bodero/templates/index.html @@ -0,0 +1,120 @@ + + + + + Chat con Gemini + + + +
+

Chat con Gemini IA

+
+ + +
+
+ + + +
+ + + diff --git a/proyecto/ronald_diaz/chat.db b/proyecto/ronald_diaz/chat.db new file mode 100644 index 0000000..bd57465 Binary files /dev/null and b/proyecto/ronald_diaz/chat.db differ diff --git a/proyecto/ronald_diaz/inicio.py b/proyecto/ronald_diaz/inicio.py new file mode 100644 index 0000000..6910947 --- /dev/null +++ b/proyecto/ronald_diaz/inicio.py @@ -0,0 +1,102 @@ +from flask import Flask, render_template, request, redirect, url_for +import sqlite3 +import os +from dotenv import load_dotenv +import google.generativeai as ai + +load_dotenv() +API = os.getenv("API_KEY") +ai.configure(api_key=API) + +preferred_models = [ + "gemini-2.5-flash", + "gemini-2.5-flash-latest", + "gemini-2.5-flash-002", + "gemini-1.5-flash", + "gemini-1.5-flash-latest", + "gemini-1.5-flash-002", +] + +model_to_use = None +for m in ai.list_models(): + if "generateContent" in m.supported_generation_methods: + for preferred in preferred_models: + if m.name == f"models/{preferred}": + model_to_use = m.name + break + if model_to_use: + break + +if not model_to_use: + raise Exception("No Gemini model available for generateContent") + +model = ai.GenerativeModel(model_to_use) +chat = model.start_chat() + +# --- Flask Setup --- +app = Flask(__name__) +DATABASE = 'chat.db' + +# --- Database Helper Functions --- +def init_db(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute(''' + CREATE TABLE IF NOT EXISTS messages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_message TEXT NOT NULL, + bot_response TEXT NOT NULL, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP + ) + ''') + conn.commit() + conn.close() + +init_db() + +@app.route('/') +def index(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("SELECT user_message, bot_response, timestamp FROM messages ORDER BY id ASC") + chat_history = c.fetchall() + conn.close() + try: + promptInicial = "Actua como un experto en recetas de postres segun el nombre del postre que ingresen debes brindar informacion sobre la receta y preparacion, la respuesta debe ser en español, en cuanto a la preparación que que la explicacion sea bien corta y entendible. Si te preguntan sobre algo que no sea un postre debes presentar el siguiente mensaje: Solo respondo respuestas sobre postres y su preparación" + chat.send_message(promptInicial) + except Exception as e: + print(f"Error: {e}") + return render_template('index.html', chat_history=chat_history) + +@app.route('/send', methods=['POST']) +def send(): + user_message = request.form['message'] + try: + response = chat.send_message(user_message) + bot_response = response.text + except Exception as e: + bot_response = f"Error: {e}" + + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("INSERT INTO messages (user_message, bot_response) VALUES (?, ?)", (user_message, bot_response)) + conn.commit() + conn.close() + + return redirect(url_for('index')) + +@app.route('/clear') +def clear(): + conn = sqlite3.connect(DATABASE) + c = conn.cursor() + c.execute("DELETE FROM messages") + conn.commit() + conn.close() + return redirect(url_for('index')) + +@app.route('/acerca') +def acercaDE(): + return render_template("acerca.html") + +if __name__ == '__main__': + app.run(debug=True) diff --git a/proyecto/ronald_diaz/templates/acerca.html b/proyecto/ronald_diaz/templates/acerca.html new file mode 100644 index 0000000..47856ca --- /dev/null +++ b/proyecto/ronald_diaz/templates/acerca.html @@ -0,0 +1,67 @@ + + + + + Acerca de – PostresChat + + + + + + + + +
+
+

Acerca de PostresChat

+

+ PostresChat es un chatbot especializado en dulces y postres. + Diseñado para responder cualquier pregunta relacionada con la selección de ingredientes, técnicas de preparación, tiempos de horneado y decoración de postres. +

+

+ Ejemplos de temas que cubre: +

    +
  • Cómo hacer un bizcocho esponjoso de vainilla
  • +
  • Alternativas sin gluten o sin lácteos
  • +
  • Técnicas de baño de chocolate y glaseado
  • +
  • Decoración con glaseado real y fondant
  • +
+

+

+ Nota: Si le preguntas algo que no tenga que ver con postres o preparación de dulces, + PostresChat te indicará amablemente que solo puede responder consultas relacionadas a postres. +

+
+
+ + + + + + \ No newline at end of file diff --git a/proyecto/ronald_diaz/templates/index.html b/proyecto/ronald_diaz/templates/index.html new file mode 100644 index 0000000..46cfeac --- /dev/null +++ b/proyecto/ronald_diaz/templates/index.html @@ -0,0 +1,92 @@ + + + + + 🤖 Chatbot con Gemini + + + + + + + +
+
+
+ {% for user_msg, bot_msg, timestamp in chat_history %} +
+
Tú: {{ user_msg }}
+
{{ timestamp }}
+
+
+
Bot: {{ bot_msg }}
+
{{ timestamp }}
+
+ {% endfor %} +
+ +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/proyecto/valeria_ramos/app.py b/proyecto/valeria_ramos/app.py new file mode 100644 index 0000000..3852d3b --- /dev/null +++ b/proyecto/valeria_ramos/app.py @@ -0,0 +1,239 @@ +from telegram import ( + Update, InlineKeyboardButton, InlineKeyboardMarkup +) +from telegram.ext import ( + ApplicationBuilder, CommandHandler, CallbackQueryHandler, + MessageHandler, ContextTypes, filters, ConversationHandler +) +import requests +import os +import re +import sqlite3 +from datetime import datetime +from dotenv import load_dotenv + +# 📌 Cargar .env +load_dotenv() +BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") +MAILJET_API_KEY = os.getenv("MAILJET_API_KEY") +MAILJET_SECRET_KEY = os.getenv("MAILJET_SECRET_KEY") +MAILJET_URL = os.getenv("MAILJET_URL") +EMAIL_FROM = os.getenv("EMAIL_FROM") + +# 📌 Estados +MENU, DATOS, AUTORIZACION, CONFIRMAR = range(4) + +# 📌 Servicios de Bodega Palermo +SERVICIOS = { + "🍷 Vinos": 25, + "🥃 Licores": 30, + "🍺 Cervezas": 15, + "🍾 Espumantes": 40 +} + +# 📌 Base de datos +conn = sqlite3.connect("bodega_palermo.db", check_same_thread=False) +cursor = conn.cursor() +cursor.execute(""" +CREATE TABLE IF NOT EXISTS chat_data ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + username TEXT, + servicio TEXT, + message_id INTEGER, + timestamp TEXT +) +""") +conn.commit() + +def guardar_interaccion(update: Update): + user = update.effective_user + username = user.username or "Sin username" + servicio = "" + message_id = None + + if update.callback_query: + servicio = update.callback_query.data + message_id = update.callback_query.message.message_id + elif update.message: + servicio = update.message.text + message_id = update.message.message_id + + timestamp = datetime.now().isoformat() + cursor.execute(""" + INSERT INTO chat_data (user_id, username, servicio, message_id, timestamp) + VALUES (?, ?, ?, ?, ?) + """, (user.id, username, servicio, message_id, timestamp)) + conn.commit() + +# 📌 Inicio con menú interactivo +async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): + mensaje = ( + "🍷 *Bienvenido a Bodega Palermo* 🍾\n\n" + "Selecciona el producto que deseas consultar por favor:" + ) + keyboard = [ + [InlineKeyboardButton(text=opcion, callback_data=opcion)] + for opcion in SERVICIOS.keys() + ] + reply_markup = InlineKeyboardMarkup(keyboard) + + await update.message.reply_text( + mensaje, + reply_markup=reply_markup, + parse_mode="Markdown" + ) + return MENU + +# 📌 Selección del producto +async def servicio_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): + query = update.callback_query + await query.answer() + servicio = query.data + context.user_data["servicio"] = servicio + + await query.message.reply_text( + f"📋 Has seleccionado *{servicio}*.\n\n" + f"Por favor, indícanos:\n1. Tu nombre completo\n2. Tu correo electrónico\n3. Detalles del pedido", + parse_mode="Markdown" + ) + guardar_interaccion(update) + return DATOS + +# 📌 Recolección de datos +async def recibir_datos(update: Update, context: ContextTypes.DEFAULT_TYPE): + texto = update.message.text.strip() + email = extraer_email(texto) + if not email: + await update.message.reply_text( + "❌ No detectamos un correo válido.\nPor favor escribe:\n`Nombre - correo@ejemplo.com - detalles del pedido`", + parse_mode="Markdown" + ) + return DATOS + + context.user_data["datos"] = texto + + await update.message.reply_text( + "🔐 ¿Autorizas a Bodega Palermo a usar tus datos para procesar tu pedido?", + reply_markup=InlineKeyboardMarkup([ + [InlineKeyboardButton("✅ Sí", callback_data="si")], + [InlineKeyboardButton("❌ No", callback_data="no")] + ]) + ) + guardar_interaccion(update) + return AUTORIZACION + +# 📌 Autorización +async def autorizacion_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): + query = update.callback_query + await query.answer() + respuesta = query.data.lower() + + if "si" in respuesta: + servicio = context.user_data["servicio"] + precio = SERVICIOS[servicio] + await query.message.reply_text( + f"💵 El precio estimado de *{servicio}* es de *${precio}* por unidad.\n\n¿Deseas confirmar tu pedido?", + parse_mode="Markdown", + reply_markup=InlineKeyboardMarkup([ + [InlineKeyboardButton("✅ Confirmar", callback_data="confirmar")], + [InlineKeyboardButton("❌ Cancelar", callback_data="cancelar")] + ]) + ) + guardar_interaccion(update) + return CONFIRMAR + else: + await query.message.reply_text( + "🚫 No podemos continuar sin tu autorización.\nUsa /start para iniciar de nuevo." + ) + return ConversationHandler.END + +# 📌 Confirmación +async def confirmar_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): + query = update.callback_query + await query.answer() + accion = query.data.lower() + + if "confirmar" in accion: + servicio = context.user_data["servicio"] + descripcion = context.user_data["datos"] + precio = SERVICIOS[servicio] + correo = extraer_email(descripcion) + + mensaje = ( + f"🍷 *Bodega Palermo* 🍾\n\n" + f"✅ *Producto:* {servicio}\n" + f"📝 *Detalles:* {descripcion}\n" + f"💵 *Precio estimado:* ${precio}\n\n" + "Nos pondremos en contacto contigo pronto. ¡Gracias por tu pedido!" + ) + + if correo: + enviado = enviar_mailjet(context, correo, f"Confirmación de pedido - Bodega Palermo", mensaje) + if enviado: + await query.message.reply_text("📧 Correo de confirmación enviado ✅") + else: + await query.message.reply_text("⚠️ Ocurrió un error al enviar el correo.") + else: + await query.message.reply_text("⚠️ Correo no detectado correctamente.") + + await query.message.reply_text("🍾 Si deseas realizar otro pedido, usa /start.") + guardar_interaccion(update) + return ConversationHandler.END + + else: + await query.message.reply_text( + "❌ Pedido cancelado. Usa /start para comenzar de nuevo cuando quieras." + ) + return ConversationHandler.END + +# 📌 Extraer correo +def extraer_email(texto): + match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', texto) + return match.group(0) if match else None + +# 📌 Enviar correo +def enviar_mailjet(context, destinatario, asunto, contenido): + data = { + "Messages": [ + { + "From": {"Email": EMAIL_FROM, "Name": "Bodega Palermo"}, + "To": [{"Email": destinatario}], + "Subject": asunto, + "TextPart": contenido + } + ] + } + try: + response = requests.post( + MAILJET_URL, + json=data, + auth=(MAILJET_API_KEY, MAILJET_SECRET_KEY) + ) + print(f"Mailjet: {response.status_code} - {response.text}") + return response.status_code == 200 + except Exception as e: + print(f"❌ Error: {e}") + return False + +# 📌 Main +def main(): + app = ApplicationBuilder().token(BOT_TOKEN).build() + + conv_handler = ConversationHandler( + entry_points=[CommandHandler("start", start)], + states={ + MENU: [CallbackQueryHandler(servicio_callback)], + DATOS: [MessageHandler(filters.TEXT & ~filters.COMMAND, recibir_datos)], + AUTORIZACION: [CallbackQueryHandler(autorizacion_callback)], + CONFIRMAR: [CallbackQueryHandler(confirmar_callback)], + }, + fallbacks=[], + ) + + app.add_handler(conv_handler) + print("🍾 Bot Bodega Palermo en ejecución...") + app.run_polling() + +if __name__ == "__main__": + main() diff --git a/proyecto/valeria_ramos/bodega_palermo.db b/proyecto/valeria_ramos/bodega_palermo.db new file mode 100644 index 0000000..ad981c3 Binary files /dev/null and b/proyecto/valeria_ramos/bodega_palermo.db differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..734e6a5 Binary files /dev/null and b/requirements.txt differ diff --git "a/valeria_Qui\303\261onez.py" "b/valeria_Qui\303\261onez.py" new file mode 100644 index 0000000..9e2c969 --- /dev/null +++ "b/valeria_Qui\303\261onez.py" @@ -0,0 +1,79 @@ +from flask import Flask, render_template, request +import requests +import math + +app = Flask(__name__) + +def obtener_pokemon(nombre_o_url): + try: + if nombre_o_url.startswith("http"): + url = nombre_o_url + else: + url = f"https://pokeapi.co/api/v2/pokemon/{nombre_o_url.lower()}" + + r = requests.get(url) + r.raise_for_status() + data = r.json() + + return { + 'name': data['name'].capitalize(), + 'image': data['sprites']['front_default'], + 'height': f"{data['height'] / 10:.1f} m", + 'weight': f"{data['weight'] / 10:.1f} kg", + 'abilities': [{'name': ability['ability']['name'].capitalize()} for ability in data['abilities']] + } + except Exception as e: + return None + +@app.route("/") +def index(): + search_query = request.args.get("search", "").strip().lower() + try: + page = int(request.args.get("page", 2)) + except ValueError: + page = 2 # si viene algo no numérico, default a 2 + + limit = 9 + offset = (page - 1) * limit + + pokemon_list = [] + total_count = 0 + + if search_query: + pokemon = obtener_pokemon(search_query) + if pokemon: + pokemon_list = [pokemon] + total_count = 3 # Asumiendo que siempre habrá 3 resultados para una búsqueda específica + else: + pokemon_list = [] + else: + try: + url = f"https://pokeapi.co/api/v2/pokemon?offset={offset}&limit={limit}" + res = requests.get(url) + res.raise_for_status() + data = res.json() + + total_count = data["count"] + for item in data["results"]: + p = obtener_pokemon(item["url"]) + if p: + pokemon_list.append(p) + except Exception as e: + pokemon_list = [] + + total_pages = math.ceil(total_count / limit) if not search_query else 1 + + # Validar que page esté entre 1 y total_pages + if page < 1: + page = 1 + elif page > total_pages: + page = total_pages if total_pages > 0 else 2 + + return render_template("index.html", + pokemon_list=pokemon_list, + search_query=search_query, + page=page, + total_pages=total_pages) + +if __name__ == "__main__": + app.run(debug=True)