[IMPROVED] Calcular tarifa de fullstack como 1.5 veces el valor máximo encontrado

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mauro Rosero P. 2025-03-12 12:57:08 -05:00
parent 9b4288492c
commit 604786ad5f
Signed by: mrosero
GPG key ID: 83BD2A5F674B7E26

View file

@ -448,6 +448,23 @@ def update_single_rate(programmer_type):
# Crear la carpeta rates si no existe # Crear la carpeta rates si no existe
os.makedirs(RATES_DIR, exist_ok=True) os.makedirs(RATES_DIR, exist_ok=True)
# Diccionario para almacenar las tarifas calculadas y existentes
rates_dict = {}
# Si es fullstack, necesitamos primero obtener el valor más alto de todos los tipos
if programmer_type == 'fullstack':
# Leer las tarifas existentes
for prog_type in get_programmer_types():
if prog_type != 'fullstack':
rate_file = RATES_DIR / f"{prog_type}.rate"
if rate_file.exists():
try:
with open(rate_file, 'r', encoding='utf-8') as f:
rates_dict[prog_type] = float(f.read().strip())
logger.info(f"Tarifa leída para {prog_type}: {rates_dict[prog_type]:.2f}")
except (FileNotFoundError, ValueError) as e:
logger.warning(f"Error al leer tarifa de {prog_type}: {e}")
# Si es bash, necesitamos primero obtener o actualizar la tarifa de devops # Si es bash, necesitamos primero obtener o actualizar la tarifa de devops
devops_rate = None devops_rate = None
if programmer_type == 'bash': if programmer_type == 'bash':
@ -460,6 +477,7 @@ def update_single_rate(programmer_type):
try: try:
with open(devops_rate_file, 'r', encoding='utf-8') as f: with open(devops_rate_file, 'r', encoding='utf-8') as f:
devops_rate = float(f.read().strip()) devops_rate = float(f.read().strip())
rates_dict['devops'] = devops_rate
logger.info(f"Tarifa leída para devops: {devops_rate:.2f}") logger.info(f"Tarifa leída para devops: {devops_rate:.2f}")
except (FileNotFoundError, ValueError) as e: except (FileNotFoundError, ValueError) as e:
logger.error(f"Error al leer tarifa de devops: {e}") logger.error(f"Error al leer tarifa de devops: {e}")
@ -502,6 +520,9 @@ def update_single_rate(programmer_type):
with open(devops_rate_file, 'w', encoding='utf-8') as f: with open(devops_rate_file, 'w', encoding='utf-8') as f:
f.write(f"{devops_rate:.2f}") f.write(f"{devops_rate:.2f}")
# Añadir al diccionario
rates_dict['devops'] = devops_rate
# Mostrar el resultado en la consola # Mostrar el resultado en la consola
result_message = f"Tarifa para devops: {devops_rate:.2f} USD/hora" result_message = f"Tarifa para devops: {devops_rate:.2f} USD/hora"
logger.info(f"Actualizado archivo {devops_rate_file} con valor: {devops_rate:.2f}") logger.info(f"Actualizado archivo {devops_rate_file} con valor: {devops_rate:.2f}")
@ -518,6 +539,47 @@ def update_single_rate(programmer_type):
logger.info(f"Calculando tarifa para bash como 0.4 * {devops_rate:.2f}") logger.info(f"Calculando tarifa para bash como 0.4 * {devops_rate:.2f}")
rate = 0.4 * devops_rate rate = 0.4 * devops_rate
logger.info(f"Tarifa calculada para bash: {rate:.2f}") logger.info(f"Tarifa calculada para bash: {rate:.2f}")
# Caso especial para fullstack
elif programmer_type == 'fullstack':
# Primero calculamos el valor más alto entre todos los tipos
max_rate_value = 0.0
for prog_type, rate_value in rates_dict.items():
if prog_type != 'fullstack' and rate_value > max_rate_value:
max_rate_value = rate_value
logger.info(f"Valor más alto encontrado: {max_rate_value:.2f}")
# Obtener tarifa para fullstack vía API
api_rate = None
if api_available:
prompt = generate_prompt_base(programmer_type)
logger.info(f"Consultando tarifa para {programmer_type}")
try:
# Consultar a Perplexity
api_rate = query_perplexity(prompt, model)
if api_rate is not None:
logger.info(f"Tarifa obtenida correctamente: {api_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}")
# Si la API falló, usar el valor predeterminado
if api_rate is None:
logger.warning(f"Usando valor predeterminado para {programmer_type}")
api_rate = get_default_rate(programmer_type)
logger.info(f"Valor predeterminado: {api_rate:.2f}")
# Calcular el valor de fullstack
# Si el valor de la API es menor o igual al valor más alto, usar 1.5 veces el valor más alto
if api_rate <= max_rate_value:
rate = 1.5 * max_rate_value
logger.info(f"API rate ({api_rate:.2f}) <= max rate ({max_rate_value:.2f}), ajustando fullstack a 1.5 * {max_rate_value:.2f} = {rate:.2f}")
else:
rate = api_rate
logger.info(f"API rate ({api_rate:.2f}) > max rate ({max_rate_value:.2f}), manteniendo valor API")
else: else:
# Para otros tipos, procedemos como antes # Para otros tipos, procedemos como antes
prompt = generate_prompt_base(programmer_type) prompt = generate_prompt_base(programmer_type)
@ -593,6 +655,23 @@ def update_rate_files(force_update=False):
programmer_types = get_programmer_types() programmer_types = get_programmer_types()
logger.info(f"Procesando {len(programmer_types)} tipos de programadores.") logger.info(f"Procesando {len(programmer_types)} tipos de programadores.")
# Diccionario para almacenar las tarifas ya calculadas
rates_dict = {}
# Leer las tarifas existentes primero
if 'fullstack' in programmer_types:
# Primero leer los valores existentes de tipos que no vamos a actualizar
for prog_type in get_programmer_types():
if prog_type not in programmer_types:
rate_file = RATES_DIR / f"{prog_type}.rate"
if rate_file.exists():
try:
with open(rate_file, 'r', encoding='utf-8') as f:
rates_dict[prog_type] = float(f.read().strip())
logger.info(f"Tarifa leída para {prog_type}: {rates_dict[prog_type]:.2f}")
except (FileNotFoundError, ValueError) as e:
logger.warning(f"Error al leer tarifa de {prog_type}: {e}")
# Procesamos primero devops siempre que force_update sea True o bash esté pendiente # Procesamos primero devops siempre que force_update sea True o bash esté pendiente
devops_rate = None devops_rate = None
need_devops_for_bash = ('bash' in programmer_types and (not (RATES_DIR / "bash.rate").exists() or force_update)) need_devops_for_bash = ('bash' in programmer_types and (not (RATES_DIR / "bash.rate").exists() or force_update))
@ -638,6 +717,9 @@ def update_rate_files(force_update=False):
with open(devops_rate_file, 'w', encoding='utf-8') as f: with open(devops_rate_file, 'w', encoding='utf-8') as f:
f.write(f"{devops_rate:.2f}") f.write(f"{devops_rate:.2f}")
# Guardar en el diccionario de tarifas
rates_dict['devops'] = devops_rate
# Mostrar el resultado en la consola # Mostrar el resultado en la consola
result_message = f"Tarifa para devops: {devops_rate:.2f} USD/hora" result_message = f"Tarifa para devops: {devops_rate:.2f} USD/hora"
logger.info(f"{'Actualizado' if force_update else 'Creado'} archivo {devops_rate_file} con valor: {devops_rate:.2f}") logger.info(f"{'Actualizado' if force_update else 'Creado'} archivo {devops_rate_file} con valor: {devops_rate:.2f}")
@ -657,18 +739,35 @@ def update_rate_files(force_update=False):
try: try:
with open(devops_rate_file, 'r', encoding='utf-8') as f: with open(devops_rate_file, 'r', encoding='utf-8') as f:
devops_rate = float(f.read().strip()) devops_rate = float(f.read().strip())
rates_dict['devops'] = devops_rate
logger.info(f"Tarifa leída para devops: {devops_rate:.2f}") logger.info(f"Tarifa leída para devops: {devops_rate:.2f}")
except (FileNotFoundError, ValueError) as e: except (FileNotFoundError, ValueError) as e:
logger.error(f"Error al leer tarifa de devops: {e}") logger.error(f"Error al leer tarifa de devops: {e}")
devops_rate = get_default_rate('devops') devops_rate = get_default_rate('devops')
rates_dict['devops'] = devops_rate
# Procesar cada tipo de programador # Procesar los demás tipos de programador antes de fullstack
fullstack_type = None
if 'fullstack' in programmer_types:
# Guardar para procesarlo después
fullstack_type = 'fullstack'
# Eliminarlo temporalmente de la lista
programmer_types.remove('fullstack')
# Procesar cada tipo de programador (excepto fullstack)
for programmer_type in programmer_types: for programmer_type in programmer_types:
# Comprobar si ya existe el archivo para este tipo de programador # Comprobar si ya existe el archivo para este tipo de programador
rate_file = RATES_DIR / f"{programmer_type}.rate" rate_file = RATES_DIR / f"{programmer_type}.rate"
# Si el archivo ya existe y no estamos forzando la actualización, saltamos este tipo # Si el archivo ya existe y no estamos forzando la actualización, saltamos este tipo
if rate_file.exists() and not force_update: if rate_file.exists() and not force_update:
# Leer el valor para almacenarlo en el diccionario
try:
with open(rate_file, 'r', encoding='utf-8') as f:
rates_dict[programmer_type] = float(f.read().strip())
except (FileNotFoundError, ValueError) as e:
logger.warning(f"Error al leer archivo {rate_file}: {e}")
logger.info(f"El archivo {rate_file} ya existe. Saltando.") logger.info(f"El archivo {rate_file} ya existe. Saltando.")
continue continue
@ -713,6 +812,9 @@ def update_rate_files(force_update=False):
logger.warning(f"Ajustando tarifa {rate:.2f} al máximo permitido de {max_rate}") logger.warning(f"Ajustando tarifa {rate:.2f} al máximo permitido de {max_rate}")
rate = max_rate rate = max_rate
# Guardar la tarifa en el diccionario
rates_dict[programmer_type] = rate
# Guardar el resultado en el archivo - solo el valor numérico con dos decimales, sin salto de línea # 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: with open(rate_file, 'w', encoding='utf-8') as f:
f.write(f"{rate:.2f}") f.write(f"{rate:.2f}")
@ -724,6 +826,76 @@ def update_rate_files(force_update=False):
# Pequeña pausa para no sobrecargar la API # Pequeña pausa para no sobrecargar la API
time.sleep(1) time.sleep(1)
# Procesar fullstack al final si está en la lista
if fullstack_type:
rate_file = RATES_DIR / f"{fullstack_type}.rate"
# Si el archivo ya existe y no estamos forzando la actualización, saltamos
if rate_file.exists() and not force_update:
# Leer el valor para mostrarlo
try:
with open(rate_file, 'r', encoding='utf-8') as f:
fullstack_rate = float(f.read().strip())
logger.info(f"El archivo {rate_file} ya existe con valor {fullstack_rate:.2f}. Saltando.")
except (FileNotFoundError, ValueError) as e:
logger.warning(f"Error al leer archivo {rate_file}: {e}")
return
# Primero calculamos el valor más alto entre todos los tipos
max_rate_value = 0.0
for prog_type, rate_value in rates_dict.items():
if prog_type != 'fullstack' and rate_value > max_rate_value:
max_rate_value = rate_value
logger.info(f"Valor más alto encontrado: {max_rate_value:.2f}")
# Obtener tarifa para fullstack vía API
api_rate = None
if api_available:
prompt = generate_prompt_base(fullstack_type)
logger.info(f"Consultando tarifa para {fullstack_type}")
try:
# Consultar a Perplexity
api_rate = query_perplexity(prompt, model)
if api_rate is not None:
logger.info(f"Tarifa obtenida correctamente: {api_rate:.2f}")
else:
logger.error(f"No se pudo obtener la tarifa para {fullstack_type}")
except Exception as e:
logger.error(f"Error al consultar tarifa para {fullstack_type}: {e}")
# Si la API falló, usar el valor predeterminado
if api_rate is None:
logger.warning(f"Usando valor predeterminado para {fullstack_type}")
api_rate = get_default_rate(fullstack_type)
logger.info(f"Valor predeterminado: {api_rate:.2f}")
# Calcular el valor de fullstack
# Si el valor de la API es menor o igual al valor más alto, usar 1.5 veces el valor más alto
if api_rate <= max_rate_value:
fullstack_rate = 1.5 * max_rate_value
logger.info(f"API rate ({api_rate:.2f}) <= max rate ({max_rate_value:.2f}), ajustando fullstack a 1.5 * {max_rate_value:.2f} = {fullstack_rate:.2f}")
else:
fullstack_rate = api_rate
logger.info(f"API rate ({api_rate:.2f}) > max rate ({max_rate_value:.2f}), manteniendo valor API")
# Limitar a tarifas menores de 200 USD/hora
max_limit = 200.00
if fullstack_rate > max_limit:
logger.warning(f"Ajustando tarifa {fullstack_rate:.2f} al máximo permitido de {max_limit}")
fullstack_rate = max_limit
# Guardar el resultado en el archivo
with open(rate_file, 'w', encoding='utf-8') as f:
f.write(f"{fullstack_rate:.2f}")
# Mostrar el resultado en la consola
result_message = f"Tarifa para {fullstack_type}: {fullstack_rate:.2f} USD/hora"
logger.info(f"{'Actualizado' if force_update and rate_file.exists() else 'Creado'} archivo {rate_file} con valor: {fullstack_rate:.2f}")
show_result(result_message)
def generate_prompt_base(programmer_type): def generate_prompt_base(programmer_type):
""" """