From 0e05c9312b92283d0a22103f9a9f1f61df6628b0 Mon Sep 17 00:00:00 2001 From: "Mauro Rosero P." Date: Wed, 12 Mar 2025 12:43:26 -0500 Subject: [PATCH] =?UTF-8?q?[ADDED]=20Implementar=20opci=C3=B3n=20--type=20?= =?UTF-8?q?para=20actualizar=20un=20tipo=20espec=C3=ADfico=20de=20programa?= =?UTF-8?q?dor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- bin/rate_update.py | 179 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 169 insertions(+), 10 deletions(-) diff --git a/bin/rate_update.py b/bin/rate_update.py index a383e36..eb4d0e2 100755 --- a/bin/rate_update.py +++ b/bin/rate_update.py @@ -421,6 +421,150 @@ def get_programmer_types(): 'odoo' ] +def update_single_rate(programmer_type): + """ + Actualiza la tarifa para un tipo específico de programador. + """ + # Verificar que el tipo de programador sea válido + if programmer_type not in get_programmer_types(): + logger.error(f"Tipo de programador no válido: {programmer_type}") + print(f"ERROR: Tipo de programador no válido: {programmer_type}") + print(f"Tipos válidos: {', '.join(get_programmer_types())}") + return False + + # Obtener modelo configurado + model = get_ai_model() + logger.info(f"Usando modelo de IA: {model}") + + # Verificar disponibilidad de la API + api_available = True + try: + # Intentar obtener la clave API (si falla, saltará una excepción) + get_perplexity_api_key() + except: + api_available = False + logger.warning("API de Perplexity no disponible. Se usarán valores predeterminados.") + + # Crear la carpeta rates si no existe + os.makedirs(RATES_DIR, exist_ok=True) + + # Si es bash, necesitamos primero obtener o actualizar la tarifa de devops + devops_rate = None + if programmer_type == 'bash': + logger.info("Actualizando tarifa de devops primero para calcular bash") + devops_rate_file = RATES_DIR / "devops.rate" + + # Comprobar si existe un archivo de devops y si debemos actualizarlo + if devops_rate_file.exists(): + # Leer la tarifa guardada de devops + try: + with open(devops_rate_file, 'r', encoding='utf-8') as f: + devops_rate = float(f.read().strip()) + logger.info(f"Tarifa leída para devops: {devops_rate:.2f}") + except (FileNotFoundError, ValueError) as e: + logger.error(f"Error al leer tarifa de devops: {e}") + # Si hay error de lectura, intentamos actualizar la tarifa + devops_rate = None + + # Si no existe o hubo error de lectura, actualizamos la tarifa de devops + if devops_rate is None: + prompt = generate_prompt_base('devops') + + # Si la API está disponible, intentar consultarla + if api_available: + logger.info("Consultando tarifa para devops") + + try: + # Consultar a Perplexity + devops_rate = query_perplexity(prompt, model) + + if devops_rate is not None: + logger.info(f"Tarifa obtenida correctamente para devops: {devops_rate:.2f}") + else: + logger.error("No se pudo obtener la tarifa para devops") + except Exception as e: + logger.error(f"Error al consultar tarifa para devops: {e}") + time.sleep(2) + + # Si la API falló o no está disponible, usar valor predeterminado + if devops_rate is None: + logger.warning("Usando valor predeterminado para devops") + devops_rate = get_default_rate('devops') + logger.info(f"Valor predeterminado para devops: {devops_rate:.2f}") + + # Limitar a tarifas menores de 200 USD/hora + max_rate = 200.00 + if devops_rate > max_rate: + logger.warning(f"Ajustando tarifa {devops_rate:.2f} al máximo permitido de {max_rate}") + devops_rate = max_rate + + # Guardar el resultado en el archivo + with open(devops_rate_file, 'w', encoding='utf-8') as f: + f.write(f"{devops_rate:.2f}") + + # Mostrar el resultado en la consola + result_message = f"Tarifa para devops: {devops_rate:.2f} USD/hora" + logger.info(f"Actualizado archivo {devops_rate_file} con valor: {devops_rate:.2f}") + show_result(result_message) + + # Pequeña pausa para no sobrecargar la API + time.sleep(1) + + # Ahora procesamos el tipo de programador solicitado + rate_file = RATES_DIR / f"{programmer_type}.rate" + + # Caso especial para bash: calculamos como 0.4 veces la tarifa de devops + if programmer_type == 'bash' and devops_rate is not None: + logger.info(f"Calculando tarifa para bash como 0.4 * {devops_rate:.2f}") + rate = 0.4 * devops_rate + logger.info(f"Tarifa calculada para bash: {rate:.2f}") + else: + # Para otros tipos, procedemos como antes + prompt = generate_prompt_base(programmer_type) + + # Variable para almacenar la tarifa + rate = None + + # Si la API está disponible, intentar consultarla + if api_available: + logger.info(f"Consultando tarifa para {programmer_type}") + + try: + # Consultar a Perplexity + rate = query_perplexity(prompt, model) + + if rate is not None: + logger.info(f"Tarifa obtenida correctamente: {rate:.2f}") + else: + logger.error(f"No se pudo obtener la tarifa para {programmer_type}") + except Exception as e: + logger.error(f"Error al consultar tarifa para {programmer_type}: {e}") + # Pequeña pausa tras un error para evitar sobrecargar la API + time.sleep(2) + + # Si la API falló o no está disponible, usar valor predeterminado + if rate is None: + logger.warning(f"Usando valor predeterminado para {programmer_type}") + rate = get_default_rate(programmer_type) + logger.info(f"Valor predeterminado: {rate:.2f}") + + # Limitar a tarifas menores de 200 USD/hora + max_rate = 200.00 + if rate > max_rate: + logger.warning(f"Ajustando tarifa {rate:.2f} al máximo permitido de {max_rate}") + rate = max_rate + + # Guardar el resultado en el archivo - solo el valor numérico con dos decimales, sin salto de línea + with open(rate_file, 'w', encoding='utf-8') as f: + f.write(f"{rate:.2f}") + + # Mostrar el resultado en la consola + result_message = f"Tarifa para {programmer_type}: {rate:.2f} USD/hora" + logger.info(f"Actualizado archivo {rate_file} con valor: {rate:.2f}") + show_result(result_message) + + return True + def update_rate_files(): """ Actualiza los archivos de tarifas con datos de Perplexity. @@ -684,6 +828,7 @@ if __name__ == "__main__": parser.add_argument('-q', '--quiet', action='store_true', help='No mostrar resultados individuales') parser.add_argument('-v', '--verbose', action='store_true', help='Mostrar información detallada del proceso') parser.add_argument('-l', '--list', action='store_true', help='Listar todas las tarifas disponibles') + parser.add_argument('-t', '--type', help='Actualizar la tarifa para un tipo específico de programador') args = parser.parse_args() # Configurar nivel de log según parámetros @@ -699,11 +844,6 @@ if __name__ == "__main__": list_rate_files() sys.exit(0) - logger.info("Iniciando actualización de tarifas...") - - if not args.quiet: - print("Actualizando tarifas...") - # Verificar e instalar pycountry si es necesario pycountry_available = check_install_pycountry() @@ -714,11 +854,30 @@ if __name__ == "__main__": logger.info("Usando lista interna para validación básica de códigos de país.") try: - # Actualizar los archivos de tarifas - update_rate_files() - - if not args.quiet: - print("Proceso de actualización de tarifas completado exitosamente.") + # Si se especifica un tipo de programador, actualizar solo ese tipo + if args.type: + logger.info(f"Actualizando tarifa para el tipo: {args.type}") + if not args.quiet: + print(f"Actualizando tarifa para {args.type}...") + + success = update_single_rate(args.type) + + if success and not args.quiet: + print(f"Tarifa para {args.type} actualizada exitosamente.") + elif not success: + sys.exit(1) + else: + # Actualizar todos los archivos de tarifas + logger.info("Iniciando actualización de tarifas...") + + if not args.quiet: + print("Actualizando tarifas...") + + update_rate_files() + + if not args.quiet: + print("Proceso de actualización de tarifas completado exitosamente.") + logger.info("Proceso de actualización de tarifas completado.") except Exception as e: logger.error(f"Error durante la actualización de tarifas: {e}")