[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:
parent
2ba3bb68ec
commit
41c40265cf
1 changed files with 57 additions and 3 deletions
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue