percentiles.rb 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # frozen_string_literal: true
  2. class AnnualReport::Percentiles < AnnualReport::Source
  3. def generate
  4. {
  5. percentiles: {
  6. followers: (total_with_fewer_followers / (total_with_any_followers + 1.0)) * 100,
  7. statuses: (total_with_fewer_statuses / (total_with_any_statuses + 1.0)) * 100,
  8. },
  9. }
  10. end
  11. private
  12. def followers_gained
  13. @followers_gained ||= @account.passive_relationships.where("date_part('year', follows.created_at) = ?", @year).count
  14. end
  15. def statuses_created
  16. @statuses_created ||= @account.statuses.where(id: year_as_snowflake_range).count
  17. end
  18. def total_with_fewer_followers
  19. @total_with_fewer_followers ||= Follow.find_by_sql([<<~SQL.squish, { year: @year, comparison: followers_gained }]).first.total
  20. WITH tmp0 AS (
  21. SELECT follows.target_account_id
  22. FROM follows
  23. INNER JOIN accounts ON accounts.id = follows.target_account_id
  24. WHERE date_part('year', follows.created_at) = :year
  25. AND accounts.domain IS NULL
  26. GROUP BY follows.target_account_id
  27. HAVING COUNT(*) < :comparison
  28. )
  29. SELECT count(*) AS total
  30. FROM tmp0
  31. SQL
  32. end
  33. def total_with_fewer_statuses
  34. @total_with_fewer_statuses ||= Status.find_by_sql([<<~SQL.squish, { comparison: statuses_created, min_id: year_as_snowflake_range.first, max_id: year_as_snowflake_range.last }]).first.total
  35. WITH tmp0 AS (
  36. SELECT statuses.account_id
  37. FROM statuses
  38. INNER JOIN accounts ON accounts.id = statuses.account_id
  39. WHERE statuses.id BETWEEN :min_id AND :max_id
  40. AND accounts.domain IS NULL
  41. GROUP BY statuses.account_id
  42. HAVING count(*) < :comparison
  43. )
  44. SELECT count(*) AS total
  45. FROM tmp0
  46. SQL
  47. end
  48. def total_with_any_followers
  49. @total_with_any_followers ||= Follow.where("date_part('year', follows.created_at) = ?", @year).joins(:target_account).merge(Account.local).count('distinct follows.target_account_id')
  50. end
  51. def total_with_any_statuses
  52. @total_with_any_statuses ||= Status.where(id: year_as_snowflake_range).joins(:account).merge(Account.local).count('distinct statuses.account_id')
  53. end
  54. end