$normalizedValues Notes normalisées sur /20 * * @return list 8 éléments */ public function calculateDistribution(array $normalizedValues): array { /** @var list $bins */ $bins = array_fill(0, 8, 0); foreach ($normalizedValues as $value) { $binIndex = min(7, max(0, (int) floor($value / 2.5))); ++$bins[$binIndex]; } return array_values($bins); } /** * Taux de réussite : pourcentage de notes >= seuil. * * @param list $normalizedValues Notes normalisées sur /20 * @param float $threshold Seuil de réussite (défaut : 10.0) */ public function calculateSuccessRate(array $normalizedValues, float $threshold = 10.0): float { if ($normalizedValues === []) { return 0.0; } $count = count($normalizedValues); $above = 0; foreach ($normalizedValues as $value) { if ($value >= $threshold) { ++$above; } } return round($above * 100.0 / $count, 1); } /** * Régression linéaire simple (moindres carrés) pour la ligne de tendance. * * @param list $points [[x, y], ...] */ public function calculateTrendLine(array $points): ?TrendResult { $n = count($points); if ($n < 2) { return null; } $sumX = 0.0; $sumY = 0.0; $sumXY = 0.0; $sumX2 = 0.0; foreach ($points as [$x, $y]) { $sumX += $x; $sumY += $y; $sumXY += $x * $y; $sumX2 += $x * $x; } $denominator = $n * $sumX2 - $sumX * $sumX; if (abs($denominator) < 1e-10) { return new TrendResult(slope: 0.0, intercept: $sumY / $n); } $slope = ($n * $sumXY - $sumX * $sumY) / $denominator; $intercept = ($sumY - $slope * $sumX) / $n; return new TrendResult( slope: round($slope, 4), intercept: round($intercept, 4), ); } /** * Détecte la tendance à partir de moyennes périodiques (trimestres). * Compare la dernière moyenne à la première avec un seuil de 1 point. * * @param list $periodicAverages Moyennes par période chronologique * * @return 'improving'|'stable'|'declining' */ public function detectTrend(array $periodicAverages): string { if (count($periodicAverages) < 2) { return 'stable'; } $first = $periodicAverages[0]; $last = $periodicAverages[count($periodicAverages) - 1]; $diff = $last - $first; if ($diff > 1.0) { return 'improving'; } if ($diff < -1.0) { return 'declining'; } return 'stable'; } /** * Calcule le percentile d'une valeur parmi un ensemble d'autres valeurs. * Indique le % de valeurs inférieures à la valeur donnée. * * @param list $otherValues */ public function calculatePercentile(float $value, array $otherValues): float { if ($otherValues === []) { return 100.0; } $below = 0; foreach ($otherValues as $other) { if ($other < $value) { ++$below; } } return round($below * 100.0 / count($otherValues), 1); } }