1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
use std::collections::HashMap; use chrono::{Datelike, NaiveDate}; use num_format::ToFormattedString; use crate::models::saved_scrobbles::SavedScrobble; use crate::utils; pub struct Stats { average_tracks_per_day: f64, average_tracks_per_week: f64, average_tracks_per_month: f64, average_tracks_per_year: f64, best_month: (String, i32), } impl Stats { pub fn new(scrobbles: &[SavedScrobble]) -> Self { Self { average_tracks_per_day: calculate_daily_average(scrobbles), average_tracks_per_week: calculate_weekly_average(scrobbles), average_tracks_per_month: calculate_monthly_average(scrobbles), average_tracks_per_year: calculate_yearly_average(scrobbles), best_month: calculate_best_month(scrobbles), } } pub fn print(&self) { println!("STATS:\n"); println!("Average Tracks Per Day: {}", self.average_tracks_per_day); println!("Average Tracks Per Week: {}", self.average_tracks_per_week); println!( "Average Tracks Per Month: {}", self.average_tracks_per_month ); println!("Average Tracks Per Year: {}", self.average_tracks_per_year); println!( "Best Month: {} ({} scrobbles)", self.best_month.0, self.best_month.1.to_formatted_string(&utils::get_locale()) ); } } fn calculate_daily_average(scrobbles: &[SavedScrobble]) -> f64 { let mut groups: HashMap<NaiveDate, i32> = HashMap::new(); scrobbles.iter().for_each(|scrobble| { let group = groups.entry(scrobble.date()).or_insert(0); *group += 1 }); groups.iter().map(|g| g.1).sum::<i32>() as f64 / utils::get_total_days(&scrobbles) as f64 } fn calculate_weekly_average(scrobbles: &[SavedScrobble]) -> f64 { let mut groups: HashMap<u32, i32> = HashMap::new(); scrobbles.iter().for_each(|scrobble| { let group = groups.entry(scrobble.date().iso_week().week()).or_insert(0); *group += 1; }); groups.iter().map(|g| g.1).sum::<i32>() as f64 / utils::get_total_weeks(&scrobbles) as f64 } fn calculate_monthly_average(scrobbles: &[SavedScrobble]) -> f64 { let mut groups: HashMap<u32, i32> = HashMap::new(); scrobbles.iter().for_each(|scrobble| { let group = groups.entry(scrobble.date().month()).or_insert(0); *group += 1; }); groups.iter().map(|g| g.1).sum::<i32>() as f64 / utils::get_total_months(&scrobbles) as f64 } fn calculate_yearly_average(scrobbles: &[SavedScrobble]) -> f64 { let mut groups: HashMap<i32, i32> = HashMap::new(); scrobbles.iter().for_each(|scrobble| { let group = groups.entry(scrobble.date().year()).or_insert(0); *group += 1 }); groups.iter().map(|g| g.1).sum::<i32>() as f64 / utils::get_total_years(&scrobbles) as f64 } fn calculate_best_month(scrobbles: &[SavedScrobble]) -> (String, i32) { let mut groups: HashMap<String, i32> = HashMap::new(); scrobbles.iter().for_each(|scrobble| { let group = groups.entry(scrobble.month_year()).or_insert(0); *group += 1 }); let mut group_vec = groups.iter().collect::<Vec<(&String, &i32)>>(); group_vec.sort_by(|a, b| a.1.cmp(b.1)); group_vec.reverse(); let best_month = group_vec.get(0).expect("Error retrieving best month"); (best_month.0.to_string(), *best_month.1) }