'use client'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar, Cell } from 'recharts'; import { SprintVelocity } from '@/lib/types'; interface PredictabilityMetricsProps { sprintHistory: SprintVelocity[]; className?: string; } interface PredictabilityDataPoint { sprint: string; planned: number; actual: number; variance: number; // Pourcentage de variance (positif = dépassement, négatif = sous-performance) accuracy: number; // Pourcentage d'exactitude (100% = parfait) } export function PredictabilityMetrics({ sprintHistory, className }: PredictabilityMetricsProps) { // Calculer les métriques de predictabilité const predictabilityData: PredictabilityDataPoint[] = sprintHistory.map(sprint => { const variance = sprint.plannedPoints > 0 ? ((sprint.completedPoints - sprint.plannedPoints) / sprint.plannedPoints) * 100 : 0; const accuracy = sprint.plannedPoints > 0 ? Math.max(0, 100 - Math.abs(variance)) : 0; return { sprint: sprint.sprintName.replace('Sprint ', ''), planned: sprint.plannedPoints, actual: sprint.completedPoints, variance: Math.round(variance * 10) / 10, accuracy: Math.round(accuracy * 10) / 10 }; }); // Calculer les statistiques globales const averageVariance = predictabilityData.length > 0 ? predictabilityData.reduce((sum, d) => sum + Math.abs(d.variance), 0) / predictabilityData.length : 0; const averageAccuracy = predictabilityData.length > 0 ? predictabilityData.reduce((sum, d) => sum + d.accuracy, 0) / predictabilityData.length : 0; const consistencyScore = averageVariance < 10 ? 'Excellent' : averageVariance < 20 ? 'Bon' : averageVariance < 30 ? 'Moyen' : 'À améliorer'; // Tendance de l'exactitude (en amélioration ou dégradation) const recentAccuracy = predictabilityData.slice(-2); const trend = recentAccuracy.length >= 2 ? recentAccuracy[1].accuracy - recentAccuracy[0].accuracy : 0; const CustomTooltip = ({ active, payload, label }: { active?: boolean; payload?: Array<{ payload: PredictabilityDataPoint; value: number; name: string; color: string }>; label?: string }) => { if (active && payload && payload.length) { const data = payload[0].payload; return (
Sprint {label}