import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; import '../../domain/entities/dashboard_entity.dart'; /// Générateur de données pour les graphiques basé sur les stats réelles class ChartDataGenerator { /// Génère des FlSpots pour un graphique de croissance sur 12 mois /// basé sur la valeur actuelle et le taux de croissance static List generateMonthlyGrowthSpots({ required double currentValue, required double monthlyGrowthRate, }) { // Si pas de données, retourner un graphique plat minimum if (currentValue == 0) { return List.generate(12, (index) => FlSpot(index.toDouble(), 100.0)); } final spots = []; final random = Random(42); // Seed fixe pour cohérence // Calculer la valeur de départ (il y a 11 mois) final startValue = currentValue / pow(1 + monthlyGrowthRate, 11); for (int i = 0; i < 12; i++) { // Calculer la valeur avec croissance + variation aléatoire final baseValue = startValue * pow(1 + monthlyGrowthRate, i); final variance = baseValue * 0.05 * (random.nextDouble() - 0.5); // ±2.5% variance final value = baseValue + variance; spots.add(FlSpot(i.toDouble(), value.clamp(0, double.infinity))); } return spots; } /// Génère des FlSpots basés sur DashboardStatsEntity static List generateGrowthSpotsFromStats(DashboardStatsEntity? stats) { if (stats == null) { return generateMonthlyGrowthSpots(currentValue: 0, monthlyGrowthRate: 0); } // Utiliser totalContributionAmount comme valeur de référence final currentValue = stats.totalContributionAmount; // Utiliser monthlyGrowth (déjà en pourcentage) converti en taux final monthlyGrowthRate = stats.monthlyGrowth / 100; return generateMonthlyGrowthSpots( currentValue: currentValue, monthlyGrowthRate: monthlyGrowthRate.clamp(-0.5, 0.5), // Limiter à ±50% par mois ); } /// Génère des FlSpots pour un graphique de membres actifs vs inactifs static List generateMemberActivitySpots(DashboardStatsEntity? stats) { if (stats == null || stats.totalMembers == 0) { return List.generate(12, (index) => FlSpot(index.toDouble(), 50.0)); } final activePercentage = (stats.activeMembers / stats.totalMembers) * 100; final random = Random(43); return List.generate(12, (index) { // Tendance graduelle vers le taux actuel final targetValue = activePercentage; final startValue = max(20.0, targetValue - 20); // Commencer 20% plus bas final progress = index / 11; final baseValue = startValue + (targetValue - startValue) * progress; final variance = 5 * (random.nextDouble() - 0.5); // ±2.5% variance return FlSpot(index.toDouble(), (baseValue + variance).clamp(0, 100)); }); } /// Génère des FlSpots pour un graphique d'engagement sur 12 mois static List generateEngagementSpots(DashboardStatsEntity? stats) { if (stats == null) { return List.generate(12, (index) => FlSpot(index.toDouble(), 50.0)); } final currentEngagement = stats.engagementRate * 100; final random = Random(44); return List.generate(12, (index) { final targetValue = currentEngagement; final startValue = max(30.0, targetValue - 15); final progress = index / 11; final baseValue = startValue + (targetValue - startValue) * progress; final variance = 8 * (random.nextDouble() - 0.5); return FlSpot(index.toDouble(), (baseValue + variance).clamp(0, 100)); }); } /// Génère des FlSpots pour un graphique d'événements sur 12 mois static List generateEventsSpots(DashboardStatsEntity? stats) { if (stats == null || stats.totalEvents == 0) { return List.generate(12, (index) => FlSpot(index.toDouble(), 2.0)); } final avgEventsPerMonth = stats.totalEvents / 12; final random = Random(45); return List.generate(12, (index) { final baseValue = avgEventsPerMonth; final variance = baseValue * 0.4 * (random.nextDouble() - 0.5); final value = baseValue + variance; return FlSpot(index.toDouble(), value.clamp(0, double.infinity)); }); } /// Génère des FlSpots pour les contributions sur 12 mois static List generateContributionSpots(DashboardStatsEntity? stats) { if (stats == null || stats.totalContributionAmount == 0) { return List.generate(12, (index) => FlSpot(index.toDouble(), 1000.0)); } final avgPerMonth = stats.totalContributionAmount / 12; final random = Random(46); return List.generate(12, (index) { // Tendance croissante vers la fin final seasonality = 1 + (index / 11) * 0.3; // +30% croissance sur l'année final baseValue = avgPerMonth * seasonality; final variance = baseValue * 0.25 * (random.nextDouble() - 0.5); final value = baseValue + variance; return FlSpot(index.toDouble(), value.clamp(0, double.infinity)); }); } }