getActiveTemplates(); } catch (\Throwable $e) { $templates = []; } } return attendance_comment_template_match($templates, $score); } } if (!function_exists('attendance_comment_template_match')) { function attendance_comment_template_match(array $templates, float $score): ?array { if ($templates === []) { return null; } // Attendance scores are percentage values; clamp to the expected domain // so minor calculation drift above 100 or below 0 does not skip a template. $score = max(0.0, min(100.0, $score)); usort($templates, static function (array $a, array $b): int { $aMin = isset($a['min_score']) ? (float) $a['min_score'] : 0.0; $bMin = isset($b['min_score']) ? (float) $b['min_score'] : 0.0; return $aMin <=> $bMin; }); foreach ($templates as $template) { $min = isset($template['min_score']) ? (float) $template['min_score'] : 0.0; $max = isset($template['max_score']) ? (float) $template['max_score'] : 100.0; if ($score >= $min && $score <= $max) { return $template; } } // Some configured bands use integer boundaries like 60-69 and 70-79, // while attendance scores contain decimals like 69.23. When the score // lands in that fractional gap, fall back to the nearest lower band. $candidate = null; foreach ($templates as $template) { $min = isset($template['min_score']) ? (float) $template['min_score'] : 0.0; if ($score < $min) { break; } $candidate = $template; } return $candidate; } }