VRFS-2916 added totals; limit month range to 1; filled out all unpopulated cols with 0; misc tweaks
This commit is contained in:
parent
5621f227b8
commit
cba86f4db4
|
|
@ -12,7 +12,7 @@ ActiveAdmin.register Cohort, :as => 'Cohorts' do
|
|||
|
||||
def scoped_collection
|
||||
objs = super
|
||||
Cohort.alltime_cohorts! if 0 == Cohort.where(all_time: true).count
|
||||
Cohort.alltime_cohorts!
|
||||
objs.where(all_time: true).order('group_start DESC')
|
||||
end
|
||||
|
||||
|
|
@ -23,46 +23,46 @@ ActiveAdmin.register Cohort, :as => 'Cohorts' do
|
|||
div(class: :cohort_col) { cc.group_start_str }
|
||||
end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:registered_users] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:registered_users] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:registered_users) }
|
||||
end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:first_downloaded_client_at] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:first_downloaded_client_at] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:first_downloaded_client_at) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:first_downloaded_client_at, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:first_certified_gear_at] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:first_certified_gear_at] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:first_certified_gear_at) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:first_certified_gear_at, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:music_sessions_user_history] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:music_sessions_user_history] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:music_sessions_user_history) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:music_sessions_user_history, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:jam_track_played] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_track_played) }
|
||||
column Cohort::ALLTIME_LABELS[:jam_tracks_played] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_tracks_played) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_track_played, true) } end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_tracks_played, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:jam_track_rights] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:jam_track_rights] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_track_rights) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_track_rights, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:recorded_tracks] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:recorded_tracks] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:recorded_tracks) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:recorded_tracks, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:friendships] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:friendships] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:friendships) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:friendships, true) } end
|
||||
|
||||
column Cohort::TOTAL_LABELS[:invited_users] do |cc|
|
||||
column Cohort::ALLTIME_LABELS[:invited_users] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:invited_users) }
|
||||
end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:invited_users, true) } end
|
||||
|
|
|
|||
|
|
@ -8,91 +8,89 @@ ActiveAdmin.register Cohort, :as => 'Cohorts Monthly' do
|
|||
config.per_page = 50
|
||||
|
||||
filter(:monthly_start, as: :select, collection: Cohort.monthly_starts)
|
||||
filter(:monthly_end, as: :select, collection: Cohort.monthly_ends)
|
||||
|
||||
controller do
|
||||
def scoped_collection
|
||||
objs = super
|
||||
args = params[:q] || {}
|
||||
if !(args[:monthly_start_eq].nil? || args[:monthly_end_eq].nil?)
|
||||
mstart, mend = Time.parse(args[:monthly_start_eq]), Time.parse(args[:monthly_end_eq])
|
||||
if mstart < mend
|
||||
Cohort.monthly_cohorts(mstart, mend) # populate monthlys
|
||||
objs = objs.where(monthly_start: mstart, monthly_end: mend)
|
||||
end
|
||||
end
|
||||
objs.where(all_time: false).order('group_start DESC')
|
||||
Cohort.monthly_cohorts!(Time.parse(args[:monthly_start_eq])) if ! args[:monthly_start_eq].nil?
|
||||
super.where(all_time: false).order('group_start DESC')
|
||||
end
|
||||
end
|
||||
|
||||
index :title => "Monthly Cohorts" do
|
||||
column 'Cohort' do |cc| cc.group_start_str end
|
||||
column Cohort::MONTHLY_LABELS[:registered_users] do |cc| cc.data_val(:registered_users) end
|
||||
index :title => proc { "Monthly Cohorts #{params[:q] ? '('+Time.parse(params[:q][:monthly_start_eq]).strftime('%Y-%m')+')' : ''}" } do
|
||||
|
||||
column 'Cohort' do |cc|
|
||||
div(class: :cohort_col) { cc.group_start_str }
|
||||
end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:registered_users] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:registered_users) }
|
||||
end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:first_downloaded_client_at] do |cc|
|
||||
cc.data_val(:first_downloaded_client_at)
|
||||
div(class: :cohort_col) { cc.data_val(:first_downloaded_client_at) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:first_downloaded_client_at, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:first_downloaded_client_at, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:first_certified_gear_at] do |cc|
|
||||
cc.data_val(:first_certified_gear_at)
|
||||
div(class: :cohort_col) { cc.data_val(:first_certified_gear_at) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:first_certified_gear_at, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:first_certified_gear_at, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:music_sessions_user_history_1] do |cc|
|
||||
cc.data_val(:music_sessions_user_history_1)
|
||||
div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_1) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:music_sessions_user_history_1, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_1, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:music_sessions_user_history_2_5] do |cc|
|
||||
cc.data_val(:music_sessions_user_history_2_5)
|
||||
div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_2_5) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:music_sessions_user_history_2_5, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_2_5, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:music_sessions_user_history_6_] do |cc|
|
||||
cc.data_val(:music_sessions_user_history_6_)
|
||||
div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_6_) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:music_sessions_user_history_6_, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:music_sessions_user_history_6_, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:jam_track_played_1] do |cc|
|
||||
cc.data_val(:jam_track_played_1)
|
||||
column Cohort::MONTHLY_LABELS[:jam_tracks_played_1] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_tracks_played_1) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:jam_track_played_1, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_tracks_played_1, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:jam_track_played_2_5] do |cc|
|
||||
cc.data_val(:jam_track_played_2_5)
|
||||
column Cohort::MONTHLY_LABELS[:jam_tracks_played_2_5] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_tracks_played_2_5) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:jam_track_played_2_5, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_tracks_played_2_5, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:jam_track_played_6_] do |cc|
|
||||
cc.data_val(:jam_track_played_6_)
|
||||
column Cohort::MONTHLY_LABELS[:jam_tracks_played_6_] do |cc|
|
||||
div(class: :cohort_col) { cc.data_val(:jam_tracks_played_6_) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:jam_track_played_6_, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_tracks_played_6_, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:jam_track_rights_redeemed] do |cc|
|
||||
cc.data_val(:jam_track_rights_redeemed)
|
||||
div(class: :cohort_col) { cc.data_val(:jam_track_rights_redeemed) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:jam_track_rights_redeemed, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_track_rights_redeemed, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:jam_track_rights] do |cc|
|
||||
cc.data_val(:jam_track_rights)
|
||||
div(class: :cohort_col) { cc.data_val(:jam_track_rights) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:jam_track_rights, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:jam_track_rights, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:recorded_tracks] do |cc|
|
||||
cc.data_val(:recorded_tracks)
|
||||
div(class: :cohort_col) { cc.data_val(:recorded_tracks) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:recorded_tracks, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:recorded_tracks, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:friendships] do |cc|
|
||||
cc.data_val(:friendships)
|
||||
div(class: :cohort_col) { cc.data_val(:friendships) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:friendships, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:friendships, true) } end
|
||||
|
||||
column Cohort::MONTHLY_LABELS[:invited_users] do |cc|
|
||||
cc.data_val(:invited_users)
|
||||
div(class: :cohort_col) { cc.data_val(:invited_users) }
|
||||
end
|
||||
column '%' do |cc| cc.data_val(:invited_users, true) end
|
||||
column '%' do |cc| div(class: :cohort_col) { cc.data_val(:invited_users, true) } end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,36 +3,38 @@ require 'date'
|
|||
class Cohort < ActiveRecord::Base
|
||||
|
||||
EARLIEST_DATE = Time.parse('2014-03-01')
|
||||
TOTAL_COHORT_DATE = Time.at(0)
|
||||
|
||||
TOTAL_LABELS = {
|
||||
ALLTIME_LABELS = {
|
||||
registered_users: 'Registered Users',
|
||||
first_downloaded_client_at: 'Downloaded app',
|
||||
first_downloaded_client_at: 'DL app',
|
||||
first_certified_gear_at: 'Certified Gear',
|
||||
music_sessions_user_history: 'Played Online',
|
||||
jam_track_played: 'Played JamTrack',
|
||||
jam_track_rights: 'Purchased JamTrack',
|
||||
jam_tracks_played: 'Played JT',
|
||||
jam_track_rights: 'Purchased JT',
|
||||
recorded_tracks: 'Made Recording',
|
||||
friendships: 'Connected w/ Friend',
|
||||
friendships: 'Friended',
|
||||
invited_users: 'Invite Others',
|
||||
}
|
||||
|
||||
MONTHLY_LABELS = {
|
||||
registered_users: 'Registered Users',
|
||||
first_downloaded_client_at: 'Downloaded app',
|
||||
first_downloaded_client_at: 'DL app',
|
||||
first_certified_gear_at: 'Certified Gear',
|
||||
music_sessions_user_history_1: 'Played Online 1',
|
||||
music_sessions_user_history_2_5: 'Played Online 2-5',
|
||||
music_sessions_user_history_6_: 'Played Online 6+',
|
||||
jam_track_played_1: 'Played Online 1',
|
||||
jam_track_played_2_5: 'Played Online 2-5',
|
||||
jam_track_played_6_: 'Played Online 6+',
|
||||
jam_track_rights_redeemed: 'Redeemed JamTrack',
|
||||
jam_track_rights: 'Purchased JamTrack',
|
||||
jam_tracks_played_1: 'Played JT 1',
|
||||
jam_tracks_played_2_5: 'Played JT 2-5',
|
||||
jam_tracks_played_6_: 'Played JT 6+',
|
||||
jam_track_rights_redeemed: 'Redeemed JT',
|
||||
jam_track_rights: 'Purchased JT',
|
||||
recorded_tracks: 'Made Recording',
|
||||
friendships: 'Connected w/ Friend',
|
||||
friendships: 'Friended',
|
||||
invited_users: 'Invite Others',
|
||||
}
|
||||
|
||||
attr_accessible :all_time, :monthly_start
|
||||
serialize :data_set, JSON
|
||||
|
||||
before_create do
|
||||
|
|
@ -87,6 +89,7 @@ class Cohort < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.generate_all_time_cohorts
|
||||
Cohort.delete_all("all_time = 't'")
|
||||
self.cohort_group_ranges.collect do |range|
|
||||
unless cc = Cohort.where(group_start: range.first).where(all_time: true).limit(1).first
|
||||
cc = Cohort.new
|
||||
|
|
@ -121,7 +124,8 @@ class Cohort < ActiveRecord::Base
|
|||
SELECT played.user_id FROM
|
||||
(SELECT user_id, COUNT(*) cnt FROM music_sessions_user_history msuh1
|
||||
WHERE
|
||||
msuh1.created_at >= '#{start_date}' AND msuh1.created_at <= '#{end_date}' AND
|
||||
msuh1.created_at >= '#{start_date}' AND
|
||||
msuh1.created_at <= '#{end_date}' AND
|
||||
EXTRACT(EPOCH FROM (msuh1.session_removed_at - msuh1.created_at)) >= 900 AND
|
||||
(SELECT COUNT(*) FROM music_sessions_user_history msuh2
|
||||
WHERE msuh1.music_session_id = msuh2.music_session_id
|
||||
|
|
@ -132,8 +136,30 @@ WHERE #{where}
|
|||
SQL
|
||||
end
|
||||
|
||||
def _played_jamtrack_subquery(constraint)
|
||||
where = if constraint.is_a?(Range)
|
||||
"played.cnt >= #{constraint.first} AND played.cnt <= #{constraint.last}"
|
||||
else
|
||||
"played.cnt #{constraint}"
|
||||
end
|
||||
start_date = all_time ? self.group_start : self.monthly_start
|
||||
end_date = all_time ? self.group_end : self.monthly_end
|
||||
sql =<<SQL
|
||||
SELECT played.player_id FROM
|
||||
(SELECT player_id, COUNT(*) cnt FROM playable_plays pp
|
||||
WHERE
|
||||
pp.created_at >= '#{start_date}' AND
|
||||
pp.created_at <= '#{end_date}' AND
|
||||
pp.playable_type = 'JamRuby::JamTrack'
|
||||
GROUP BY player_id
|
||||
) played
|
||||
WHERE #{where}
|
||||
SQL
|
||||
end
|
||||
|
||||
def _subquery(assoc_key, num_user)
|
||||
assoc = User.reflections[assoc_key]
|
||||
return 0 unless assoc
|
||||
start_date = all_time ? self.group_start : self.monthly_start
|
||||
end_date = all_time ? self.group_end : self.monthly_end
|
||||
sql =<<SQL
|
||||
|
|
@ -194,17 +220,17 @@ SQL
|
|||
count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
_put_data_set(:music_sessions_user_history_6_, count, num_user)
|
||||
|
||||
# sql = _played_jamtrack_subquery(' = 1 ')
|
||||
# count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
# _put_data_set(:jam_track_played_1, count, num_user)
|
||||
sql = _played_jamtrack_subquery(' = 1 ')
|
||||
count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
_put_data_set(:jam_tracks_played_1, count, num_user)
|
||||
|
||||
# sql = _played_jamtrack_subquery(2..5)
|
||||
# count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
# _put_data_set(:jam_track_played_2_5, count, num_user)
|
||||
sql = _played_jamtrack_subquery(2..5)
|
||||
count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
_put_data_set(:jam_tracks_played_2_5, count, num_user)
|
||||
|
||||
# sql = _played_jamtrack_subquery(' >= 6')
|
||||
# count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
# _put_data_set(:jam_track_played_6_, count, num_user)
|
||||
sql = _played_jamtrack_subquery(' >= 6')
|
||||
count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
_put_data_set(:jam_tracks_played_6_, count, num_user)
|
||||
|
||||
self.save!
|
||||
end
|
||||
|
|
@ -247,8 +273,10 @@ SQL
|
|||
count = _subquery(assoc_key = :jam_track_rights, num_user)
|
||||
_put_data_set(assoc_key, count, num_user)
|
||||
|
||||
# count = _subquery(assoc_key = :jam_track_played, num_user)
|
||||
# _put_data_set(assoc_key, count, num_user)
|
||||
count = _subquery(assoc_key = :jam_tracks_played, num_user) do |subsql|
|
||||
subsql += " AND tt.playable_type = 'JamRuby::JamTrack' "
|
||||
end
|
||||
_put_data_set(assoc_key, count, num_user)
|
||||
|
||||
sql = _played_online_subquery(' >= 1')
|
||||
count = self.class.cohort_users(self).where("users.id IN (#{sql})").count
|
||||
|
|
@ -261,20 +289,50 @@ SQL
|
|||
self.all_time ? _all_time! : _monthly!
|
||||
end
|
||||
|
||||
def self.alltime_cohorts!
|
||||
Cohort.generate_all_time_cohorts.each do |cc|
|
||||
cc._all_time!
|
||||
def calculate_totals(cohorts)
|
||||
self.group_start = self.group_end = TOTAL_COHORT_DATE
|
||||
labels = all_time ? Cohort::ALLTIME_LABELS : Cohort::MONTHLY_LABELS
|
||||
|
||||
self.data_set = labels.inject({}) do |hh, (kk,vv)|
|
||||
hh[kk.to_s] = hh["#{kk}%"] = 0
|
||||
hh
|
||||
end
|
||||
|
||||
labels = labels.keys.map(&:to_s)
|
||||
cohorts.each do |cc|
|
||||
labels.each do |key|
|
||||
self.data_set[key] += cc.data_set[key].to_i
|
||||
end
|
||||
end
|
||||
|
||||
user_total = self.data_set['registered_users'].to_f
|
||||
labels.delete('registered_users')
|
||||
labels.each do |key|
|
||||
xx = (self.data_set[key].to_f / user_total)
|
||||
self.data_set["#{key}%"] = 100.0 * xx.round(4)
|
||||
end
|
||||
|
||||
self.save!
|
||||
cohorts << self
|
||||
end
|
||||
|
||||
def self.monthly_cohorts(monthly_start, monthly_end)
|
||||
self.generate_monthly_cohorts(monthly_start, monthly_end).compact.each do |cc|
|
||||
def self.alltime_cohorts!
|
||||
cohorts = Cohort.generate_all_time_cohorts.each do |cc|
|
||||
cc._all_time!
|
||||
end
|
||||
Cohort.new(all_time: true).calculate_totals(cohorts)
|
||||
end
|
||||
|
||||
def self.monthly_cohorts!(monthly_start, monthly_end=nil)
|
||||
monthly_end ||= monthly_start + 1.month - 1.second
|
||||
cohorts = self.generate_monthly_cohorts(monthly_start, monthly_end).compact.each do |cc|
|
||||
cc._monthly!
|
||||
end
|
||||
Cohort.new(all_time: false, monthly_start: monthly_start).calculate_totals(cohorts)
|
||||
end
|
||||
|
||||
def group_start_str
|
||||
self.group_start.strftime('%Y-%m')
|
||||
is_total_cohort? ? 'Total' : self.group_start.strftime('%Y-%m')
|
||||
end
|
||||
|
||||
def group_end_str
|
||||
|
|
@ -296,10 +354,8 @@ SQL
|
|||
end
|
||||
end
|
||||
|
||||
def self.monthly_ends
|
||||
self.cohort_group_ranges.collect do |rr|
|
||||
rr.last.to_s
|
||||
end
|
||||
def is_total_cohort?
|
||||
self.group_start == TOTAL_COHORT_DATE
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue