user_downloads/
user-downloads.rs1use chrono::Utc;
7use db_dump::Date;
8use std::collections::{BTreeMap as Map, BTreeSet as Set};
9
10const USER: &str = "dtolnay";
11
12#[derive(Default)]
13struct Downloads {
14 theirs: u64,
15 all: u64,
16}
17
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 let user_id = user_id.expect("no such user");
36
37 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}