import psutil

class HardwarePhase:
    """
    Una clase para calcular el número óptimo de trabajadores basado en los recursos del sistema,
    permitiendo un porcentaje configurable de uso de memoria.

    Esta clase recupera automáticamente la memoria total y los núcleos lógicos del sistema,
    y calcula el número óptimo de trabajadores para el procesamiento paralelo.

    Atributos:
        total_memory_gb (float): Memoria total del sistema en gigabytes.
        logical_cores (int): Número de núcleos lógicos de CPU en el sistema.
        memory_usage_percentage (float): Porcentaje del total de la memoria a usar para el cálculo.
    """

    def __init__(self, memory_usage_percentage=80):
        """
        Inicializa HardwarePipeline con la memoria total del sistema y el conteo de núcleos lógicos,
        y establece el porcentaje de uso de memoria.

        Argumentos:
            memory_usage_percentage (float): Porcentaje del total de la memoria a utilizar para el cálculo.
        """
        self.total_memory_gb = psutil.virtual_memory().available / (1024 ** 3)  # Convierte bytes a GB
        self.logical_cores = psutil.cpu_count(logical=True)
        self.memory_usage_percentage = memory_usage_percentage / 100  # Convierte el porcentaje a fracción

    def calculate_optimal_workers(self):
        """
        Calcula el número óptimo de trabajadores basado en la memoria disponible y los núcleos lógicos.

        El cálculo asume que cada trabajador debe tener al menos 0.5 GB de memoria.
        El número de trabajadores no debe exceder el número de núcleos lógicos.
        """
        usable_memory_gb = self.total_memory_gb * self.memory_usage_percentage
        memory_based_workers = int(usable_memory_gb / 0.5)
        optimal_workers = max(min(memory_based_workers, self.logical_cores), 1)
        self.optimal_workers = optimal_workers
        print('MEMORIA UTILIZABLE', usable_memory_gb)
        print('NÚCLEOS LÓGICOS', self.logical_cores)

    def run_pipeline(self):
        """
        Ejecuta el pipeline para calcular el número óptimo de trabajadores.
        """
        self.calculate_optimal_workers()