crate_activity/
analyze.rs

1crate::ix!();
2
3pub fn analyze_usage(crate_name: &str, version_downloads: Vec<VersionDownload>) -> CrateUsageSummary {
4
5    // Aggregate downloads by date
6    let mut daily_downloads: HashMap<NaiveDate, i64> = HashMap::new();
7
8    for download in version_downloads.iter() {
9        *daily_downloads.entry(*download.date()).or_insert(0) += download.downloads();
10    }
11
12    let total_downloads: i64 = daily_downloads.values().sum();
13    let average_daily_downloads = total_downloads as f64 / daily_downloads.len() as f64;
14    let peak_daily_downloads = *daily_downloads.values().max().unwrap_or(&0);
15
16    // Calculate trend (simple: increasing, decreasing, or stable)
17    let mut trend = None;
18    let mut diffs = Vec::new();
19    let mut sorted_days: Vec<_> = daily_downloads.into_iter().collect();
20    sorted_days.sort_by_key(|&(date, _)| date);
21
22    for i in 1..sorted_days.len() {
23        diffs.push(sorted_days[i].1 as i64 - sorted_days[i - 1].1 as i64);
24    }
25
26    if !diffs.is_empty() {
27        let positive_diffs = diffs.iter().filter(|&&d| d > 0).count();
28        let negative_diffs = diffs.iter().filter(|&&d| d < 0).count();
29
30        trend = if positive_diffs > negative_diffs {
31            Some(DownloadTrend::Increasing)
32        } else if negative_diffs > positive_diffs {
33            Some(DownloadTrend::Decreasing)
34        } else {
35            Some(DownloadTrend::Stable)
36        };
37    }
38
39    // Use the builder to construct the summary
40    CrateUsageSummaryBuilder::default()
41        .crate_name(crate_name.to_string())
42        .total_downloads(total_downloads)
43        .average_daily_downloads(average_daily_downloads)
44        .peak_daily_downloads(peak_daily_downloads)
45        .download_trend(trend)
46        .version_downloads(version_downloads)
47        .build()
48        .expect("Failed to build CrateUsageSummary") // Handle errors from builder
49}