22// for details. All rights reserved. Use of this source code is governed by a
33// BSD-style license that can be found in the LICENSE file.
44
5- const minAvgDailyDownloadsThreshold = 1000 ;
65const analysisWindowDays = 30 ;
7- const weightAge = 0.25 ;
8- const weightGrowthRate = 0.75 ;
96
107/// Calculates the relative daily growth rate of a package's downloads.
118///
@@ -14,36 +11,30 @@ const weightGrowthRate = 0.75;
1411/// over the last ([analysisWindowDays] ) days to determine how fast a package is
1512/// growing relative to its own current download volume.
1613///
17- /// Returns -double.maxFinite:
18- /// - If the [totalDownloads] list has fewer data points than
19- /// [analysisWindowDays] .
20- /// - If the average daily downloads over the [analysisWindowDays] period are
21- /// less than [minAvgDailyDownloadsThreshold] .
22- ///
23- /// Otherwise, it returns the calculated relative growth rate. A positive value
24- /// indicates an upward trend in downloads, while a negative value indicates a
25- /// downward trend. The magnitude represents the growth (or decline) rate
26- /// normalized by the average daily downloads, allowing for comparison across
27- /// packages of different popularity. For example, a slope of +10 downloads/day
28- /// is more significant for a package with 100 average daily downloads (10%
29- /// relative growth) than for a package with 10000 average daily downloads (0.1%
30- /// relative growth).
14+ /// A positive value indicates an upward trend in downloads, while a negative
15+ /// value indicates a downward trend. The magnitude represents the growth (or
16+ /// decline) rate normalized by the average daily downloads, allowing for
17+ /// comparison across packages of different popularity. For example, a slope of
18+ /// +10 downloads/day is more significant for a package with 100 average daily
19+ /// downloads (10% relative growth) than for a package with 10000 average daily
20+ /// downloads (0.1% relative growth).
3121double computeRelativeGrowthRate (List <int > totalDownloads) {
22+ final List <int > data;
3223 if (totalDownloads.length < analysisWindowDays) {
33- // insufficient data points.
34- return - double .maxFinite;
24+ data = [
25+ ...totalDownloads,
26+ ...List .filled (analysisWindowDays - totalDownloads.length, 0 )
27+ ];
28+ } else {
29+ data = totalDownloads;
3530 }
3631
37- final recentDownloads = totalDownloads .sublist (0 , analysisWindowDays);
32+ final recentDownloads = data .sublist (0 , analysisWindowDays);
3833
3934 final averageRecentDownloads =
4035 recentDownloads.reduce ((prev, element) => prev + element) /
4136 recentDownloads.length;
4237
43- if (averageRecentDownloads < minAvgDailyDownloadsThreshold) {
44- // Package does not meet the minimum average download threshold.
45- return - double .maxFinite;
46- }
4738 // We reverse the recentDownloads list for regression, since the first entry
4839 // is the newest point in time. By reversing, we pass the data in
4940 // chronological order.
0 commit comments