110%: red (over-allocated) */ public function getIndicator(float $utilization): string { if ($utilization < self::THRESHOLD_UNDERUTILIZED) { return self::INDICATOR_GRAY; } if ($utilization < self::THRESHOLD_LOW) { return self::INDICATOR_BLUE; } if ($utilization <= self::THRESHOLD_OPTIMAL) { return self::INDICATOR_GREEN; } if ($utilization <= self::THRESHOLD_CAUTION) { return self::INDICATOR_YELLOW; } return self::INDICATOR_RED; } /** * Get display color for UI frameworks (maps yellow to amber). */ public function getDisplayColor(float $utilization): string { return match ($this->getIndicator($utilization)) { self::INDICATOR_GRAY => 'gray', self::INDICATOR_BLUE => 'blue', self::INDICATOR_GREEN => 'green', self::INDICATOR_YELLOW => 'amber', self::INDICATOR_RED => 'red', default => 'gray', }; } /** * Get status description for utilization level. */ public function getStatusDescription(float $utilization): string { return match ($this->getIndicator($utilization)) { self::INDICATOR_GRAY => 'Under-utilized', self::INDICATOR_BLUE => 'Low utilization', self::INDICATOR_GREEN => 'Optimal', self::INDICATOR_YELLOW => 'High utilization', self::INDICATOR_RED => 'Over-allocated', default => 'Unknown', }; } /** * Format utilization percentage for display. */ public function formatPercentage(float $utilization, int $decimals = 1): string { return number_format($utilization, $decimals).'%'; } /** * Format hours for display. */ public function formatHours(float $hours, int $decimals = 1): string { return number_format($hours, $decimals).'h'; } /** * Get Tailwind CSS classes for utilization badge. */ public function getTailwindClasses(float $utilization): array { $indicator = $this->getIndicator($utilization); return [ 'bg' => match ($indicator) { self::INDICATOR_GRAY => 'bg-gray-100', self::INDICATOR_BLUE => 'bg-blue-100', self::INDICATOR_GREEN => 'bg-green-100', self::INDICATOR_YELLOW => 'bg-yellow-100', self::INDICATOR_RED => 'bg-red-100', default => 'bg-gray-100', }, 'text' => match ($indicator) { self::INDICATOR_GRAY => 'text-gray-700', self::INDICATOR_BLUE => 'text-blue-700', self::INDICATOR_GREEN => 'text-green-700', self::INDICATOR_YELLOW => 'text-yellow-700', self::INDICATOR_RED => 'text-red-700', default => 'text-gray-700', }, 'border' => match ($indicator) { self::INDICATOR_GRAY => 'border-gray-300', self::INDICATOR_BLUE => 'border-blue-300', self::INDICATOR_GREEN => 'border-green-300', self::INDICATOR_YELLOW => 'border-yellow-300', self::INDICATOR_RED => 'border-red-300', default => 'border-gray-300', }, ]; } /** * Get DaisyUI badge class for utilization indicator. */ public function getDaisyuiBadgeClass(float $utilization): string { return match ($this->getIndicator($utilization)) { self::INDICATOR_GRAY => 'badge-neutral', self::INDICATOR_BLUE => 'badge-info', self::INDICATOR_GREEN => 'badge-success', self::INDICATOR_YELLOW => 'badge-warning', self::INDICATOR_RED => 'badge-error', default => 'badge-neutral', }; } /** * Format a complete utilization response with all display metadata. */ public function formatUtilizationResponse(float $utilization, float $capacity, float $allocated): array { return [ 'capacity' => round($capacity, 2), 'allocated' => round($allocated, 2), 'utilization' => round($utilization, 1), 'indicator' => $this->getIndicator($utilization), 'display' => [ 'percentage' => $this->formatPercentage($utilization), 'color' => $this->getDisplayColor($utilization), 'status' => $this->getStatusDescription($utilization), 'badge_class' => $this->getDaisyuiBadgeClass($utilization), ], ]; } }