[IMPROVED] Usar tarifa fullstack.rate × 176 como costo por persona-mes

🤖 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 14:06:42 -05:00
parent 2ba3bb68ec
commit 41c40265cf
Signed by: mrosero
GPG key ID: 83BD2A5F674B7E26

View file

@ -31,6 +31,11 @@ logger.addHandler(console_handler)
# Variable para controlar si se muestra el resultado en la consola
SHOW_RESULTS = True
# Directorio base del proyecto
BASE_DIR = Path(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
CONFIG_DIR = BASE_DIR / 'bin' / 'config'
RATES_DIR = CONFIG_DIR / 'rates' # Ubicación para archivos de tarifas
# Constantes para el modelo COCOMO básico
COCOMO_MODELS = {
# [a, b, c, d] - Coeficientes para Esfuerzo = a * (KLOC^b) y Tiempo = c * (Esfuerzo^d)
@ -39,6 +44,9 @@ COCOMO_MODELS = {
'embedded': [3.6, 1.20, 2.5, 0.32] # Proyectos complejos
}
# Número de horas laborables en un mes (22 días x 8 horas)
HOURS_PER_MONTH = 176
# Extensiones de archivo a considerar por defecto
DEFAULT_EXTENSIONS = [
'.py', '.java', '.c', '.cpp', '.cc', '.cxx', '.h', '.hpp', '.js', '.ts',
@ -242,6 +250,33 @@ def determine_cocomo_model(loc):
else:
return 'embedded' # Proyectos grandes (más de 300K líneas)
def get_fullstack_rate():
"""
Obtiene la tarifa por hora de un desarrollador fullstack desde el archivo de configuración.
Si el archivo no existe, devuelve un valor predeterminado de 45.00 USD/hora.
Returns:
Float: Tarifa por hora en USD
"""
rate_file = RATES_DIR / "fullstack.rate"
# Comprobar si existe el archivo
if not rate_file.exists():
logger.warning(f"No se encontró el archivo de tarifa: {rate_file}")
logger.warning("Usando tarifa predeterminada de 45.00 USD/hora")
return 45.00
# Leer la tarifa del archivo
try:
with open(rate_file, 'r', encoding='utf-8') as f:
rate = float(f.read().strip())
logger.info(f"Tarifa leída desde {rate_file}: {rate:.2f} USD/hora")
return rate
except (FileNotFoundError, ValueError, IOError) as e:
logger.warning(f"Error al leer el archivo de tarifa {rate_file}: {e}")
logger.warning("Usando tarifa predeterminada de 45.00 USD/hora")
return 45.00
def print_results(results):
"""
Imprime los resultados del cálculo COCOMO de manera formateada.
@ -268,8 +303,8 @@ if __name__ == "__main__":
parser.add_argument('--project', required=True, help='Ruta del directorio del proyecto a analizar')
parser.add_argument('--model', choices=['organic', 'semi-detached', 'embedded', 'auto'],
default='auto', help='Tipo de modelo COCOMO a utilizar (por defecto: auto)')
parser.add_argument('--cost', type=float, default=5000.0,
help='Costo por persona-mes en USD (por defecto: 5000)')
parser.add_argument('--cost', type=float,
help='Costo por persona-mes en USD (por defecto: tarifa fullstack × 176)')
parser.add_argument('--ignore', action='append',
help='Patrones adicionales de archivos a ignorar')
parser.add_argument('--ext', action='append',
@ -295,6 +330,25 @@ if __name__ == "__main__":
print(f"ERROR: El directorio del proyecto no existe: {args.project}")
sys.exit(1)
# Verificar que el directorio de tarifas existe
if not RATES_DIR.exists():
logger.warning(f"El directorio de tarifas no existe: {RATES_DIR}")
logger.warning("Se creará el directorio y se usarán valores predeterminados.")
try:
os.makedirs(RATES_DIR, exist_ok=True)
except Exception as e:
logger.error(f"Error al crear el directorio de tarifas: {e}")
# Obtener costo por hora desde fullstack.rate y convertir a costo por persona-mes
if args.cost is None:
# Obtener la tarifa por hora y multiplicar por las horas mensuales
hourly_rate = get_fullstack_rate()
cost_per_pm = hourly_rate * HOURS_PER_MONTH
logger.info(f"Costo por hora: ${hourly_rate:.2f} × {HOURS_PER_MONTH} horas = ${cost_per_pm:.2f} por persona-mes")
else:
cost_per_pm = args.cost
logger.info(f"Usando costo por persona-mes especificado: ${cost_per_pm:.2f}")
# Preparar extensiones y patrones de ignorar
extensions = DEFAULT_EXTENSIONS.copy()
if args.ext:
@ -316,7 +370,7 @@ if __name__ == "__main__":
model_type = args.model
# Calcular estimaciones COCOMO
results = estimate_cocomo(loc, model_type, args.cost)
results = estimate_cocomo(loc, model_type, cost_per_pm)
# Añadir ruta del proyecto para la presentación
results['project_path'] = str(project_path)