133 lines
4.9 KiB
Dart
133 lines
4.9 KiB
Dart
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<FlSpot> 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 = <FlSpot>[];
|
|
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<FlSpot> 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<FlSpot> 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<FlSpot> 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<FlSpot> 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<FlSpot> 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));
|
|
});
|
|
}
|
|
}
|