diff --git a/admin/app/models/cohort.rb b/admin/app/models/cohort.rb index d1213fe53..cf18df9ab 100644 --- a/admin/app/models/cohort.rb +++ b/admin/app/models/cohort.rb @@ -8,7 +8,7 @@ class Cohort < ActiveRecord::Base registered_users: 'Registered Users', first_downloaded_client_at: 'Downloaded app', first_certified_gear_at: 'Certified Gear', - music_sessions_user_history: 'Played Online', + music_sessions_user_history: 'Played Online', play_jamtr: 'Played JamTrack', jam_track_rights: 'Purchased JamTrack', recorded_tracks: 'Made Recording', @@ -17,7 +17,21 @@ class Cohort < ActiveRecord::Base } # KEY_SET_TOTAL = [:registered_users, :first_downloaded_client_at, :first_certified_gear_at, :music_session_histories, 'play_jamtr', :jam_track_rights, :recordings, :friendships, :invited_users] - KEY_SET_MONTH = ['reg_users', :first_downloaded_client_at, :first_certified_gear_at, 'visit0-1', 'visit2-5', 'visit6+', 'play_online0-1', 'play_online2-5', 'play_online6+', 'play_jamtr0-1', 'play_jamtr2-5', 'play_jamtr6+', 'redeem_jamtr', 'purch_jamtr', 'recordings', 'friendships', 'invited_users'] + KEY_SET_MONTH = [:registered_users, :first_downloaded_client_at, :first_certified_gear_at, :visit_1, :visit_2_5, :visit_6_, :play_online_1, :play_online_2_5, :play_online_6_, :play_jamtr_1, :play_jamtr_2_5, :play_jamtr_6_, :jam_track_rights_redeemed, :jam_track_rights, :recorded_tracks, :friendships, :invited_users] + + MONTHLY_LABELS = { + registered_users: 'Registered Users', + first_downloaded_client_at: 'Downloaded 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+', + play_jamtr: 'Played JamTrack', + jam_track_rights: 'Purchased JamTrack', + recorded_tracks: 'Made Recording', + friendships: 'Connected w/Friend', + invited_users: 'Invite Others', + } serialize :data_set, JSON @@ -38,9 +52,9 @@ class Cohort < ActiveRecord::Base .map { |d| [d.year,d.mon,d.day].first(prec) } end - def self.cohort_date_ranges - starting = User.where(admin: false).order(:created_at).first.created_at - ending = Time.now + def self.cohort_date_ranges(starting=nil, ending=nil) + starting ||= User.where(admin: false).order(:created_at).first.created_at + ending ||= Time.now dates = self.date_tuples([starting.year, starting.month], [ending.year, ending.month]) ranges = [] @@ -52,6 +66,18 @@ class Cohort < ActiveRecord::Base ranges end + def self.monthly_cohorts(start_date, end_date) + self.cohort_date_ranges(start_date, end_date).collect do |range| + unless cc = Cohort.where(start_date: range.first).where(cumulative: true).limit(1).first + cc = Cohort.new + cc.start_date = range.first + cc.end_date = range.last + cc.save! + end + cc + end + end + def self.cumulative_cohorts self.cohort_date_ranges.collect do |range| unless cc = Cohort.where(start_date: range.first).where(cumulative: true).limit(1).first @@ -65,7 +91,7 @@ class Cohort < ActiveRecord::Base end end - def _join_user(assoc_ref) + def _join_user_all_time(assoc_ref) assoc_ref.active_record .joins("INNER JOIN users AS uu ON uu.id = #{assoc_ref.foreign_key}") .where(created_at: self.start_date..self.end_date) @@ -73,6 +99,10 @@ class Cohort < ActiveRecord::Base self.start_date, self.end_date]) end + def _attribute_within_monthly(active_record, attrib) + active_record.where(attrib => self.start_date..self.end_date) + end + def _put_data_set(key, count, num_user) self.data_set[key] = count self.data_set["#{key}%"] = 100.0 * (count.to_f / num_user.to_f) @@ -82,9 +112,30 @@ class Cohort < ActiveRecord::Base User.where(attrib => cohort.start_date..cohort.end_date) end - def all_time! - num_user = self.class.user_attribute_within(:created_at, self).count - return unless 0 < num_user + def _monthly_played_online_count(constraint) + where = if constraint.is_a?(Range) + "played.cnt >= #{constraint.first} AND played.cnt <= #{constraint.last}" + else + "played.cnt = #{constraint}" + end + sql =<= '#{self.start_date}' AND created_at <= '#{self.end_date}' AND + EXTRACT(EPOCH FROM (session_removed_at - created_at)) >= 900 + GROUP BY user_id + ) played +WHERE #{where} +SQL + MusicSessionUserHistory.connection.execute(sql)[0]['count'].to_i + end + + def _monthly! + unless 0 < num_user = self.class.user_attribute_within(:created_at, self).count + self.update_attribute(:data_set, {}) + return + end self.data_set['registered_users'] = num_user num_user = num_user.to_f @@ -95,36 +146,75 @@ class Cohort < ActiveRecord::Base count = self.class.user_attribute_within(:first_certified_gear_at, self).count _put_data_set('first_certified_gear_at', count, num_user) - count = _join_user(InvitedUser.reflections[:sender]).count + count = _attribute_within_monthly(InvitedUser, :created_at).count _put_data_set('invited_users', count, num_user) - count = _join_user(RecordedTrack.reflections[:user]).count + count = _attribute_within_monthly(RecordedTrack, :created_at).count _put_data_set('recorded_tracks', count, num_user) - count = _join_user(Friendship.reflections[:user]) + count = _attribute_within_monthly(JamTrackRight, :created_at).count + _put_data_set('jam_track_rights', count, num_user) + + count = _attribute_within_monthly(JamTrackRight, :created_at) + .where(redeemed: true) + .count + _put_data_set('jam_track_rights_redeemed', count, num_user) + + count = _attribute_within_monthly(Friendship, :created_at) + .joins("INNER JOIN friendships AS fff ON fff.friend_id = friendships.user_id") + .where(['fff.created_at >= ? AND fff.created_at <= ?', + self.start_date, self.end_date]).count + count /= 2 + _put_data_set('friendships', count, num_user) + + count = self._monthly_played_online_count(1) + _put_data_set('music_sessions_user_history_1', count, num_user) + + end + + def _all_time! + unless 0 < num_user = self.class.user_attribute_within_monthly(:created_at, self).count + self.update_attribute(:data_set, {}) + return + end + + self.data_set['registered_users'] = num_user + num_user = num_user.to_f + + count = self.class.user_attribute_within(:first_downloaded_client_at, self) + .where(created_at: self.start_date..self.end_date) + .count + _put_data_set('first_downloaded_client_at', count, num_user) + + count = self.class.user_attribute_within(:first_certified_gear_at, self) + .where(created_at: self.start_date..self.end_date) + .count + _put_data_set('first_certified_gear_at', count, num_user) + + count = _join_user_all_time(InvitedUser.reflections[:sender]).count + _put_data_set('invited_users', count, num_user) + + count = _join_user_all_time(RecordedTrack.reflections[:user]).count + _put_data_set('recorded_tracks', count, num_user) + + count = _join_user_all_time(Friendship.reflections[:user]) .joins("INNER JOIN friendships AS fff ON fff.friend_id = uu.id") .where(['fff.created_at >= ? AND fff.created_at <= ?', self.start_date, self.end_date]).count count /= 2 _put_data_set('friendships', count, num_user) - count = _join_user(JamTrackRight.reflections[:user]).count + count = _join_user_all_time(JamTrackRight.reflections[:user]).count _put_data_set('jam_track_rights', count, num_user) - count = _join_user(MusicSessionUserHistory.reflections[:user]).count + count = _join_user_all_time(MusicSessionUserHistory.reflections[:user]).count _put_data_set('music_sessions_user_history', count, num_user) self.save! end - def monthly! - count = JamTrackRight - .where(redeemed: true) - .where(updated_at: self.start_date..self.end_date) - .count - self.data_set['redeemed_jamtracks'] = count - self.data_set["redeemed_jamtracks%"] = 100.0 * (count.to_f / num_user.to_f) - + def populate! + self.cumulative ? _all_time! : _monthly! end end