[dw-free] Business statistics
[commit: http://hg.dwscoalition.org/dw-free/rev/c557c814bf14]
http://bugs.dwscoalition.org/show_bug.cgi?id=124
Add statistics gathering to break down activity by paid account type.
Patch by
pauamma.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=124
Add statistics gathering to break down activity by paid account type.
Patch by
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Files modified:
- cgi-bin/DW/Pay.pm
- cgi-bin/DW/StatData/ActiveAccounts.pm
- cgi-bin/DW/StatData/PaidAccounts.pm
-------------------------------------------------------------------------------- diff -r f1b881e72e8d -r c557c814bf14 cgi-bin/DW/Pay.pm --- a/cgi-bin/DW/Pay.pm Wed Nov 25 04:18:51 2009 +0000 +++ b/cgi-bin/DW/Pay.pm Wed Nov 25 05:14:57 2009 +0000 @@ -38,7 +38,8 @@ use constant ERR_TEMP => 2; # RETURN: 1/0 if the type is a valid type # sub type_is_valid { - return 1 if $LJ::CAP{$_[0]} && $LJ::CAP{$_[0]}->{_account_type}; + return 1 if $LJ::CAP{$_[0]} && $LJ::CAP{$_[0]}->{_account_type} + && $LJ::CAP{$_[0]}->{_visible_name}; return 0; } @@ -52,9 +53,41 @@ sub type_is_valid { # RETURN: string name of type, else undef # sub type_name { - confess 'invalid typeid' + confess "invalid typeid $_[0]" unless DW::Pay::type_is_valid( $_[0] ); return $LJ::CAP{$_[0]}->{_visible_name}; +} + +################################################################################ +# DW::Pay::type_shortname +# +# ARGUMENTS: typeid +# +# typeid required the id of the type we're checking +# +# RETURN: string short name of type, else undef +# +sub type_shortname { + confess "invalid typeid $_[0]" + unless DW::Pay::type_is_valid( $_[0] ); + return $LJ::CAP{$_[0]}->{_account_type}; +} + +################################################################################ +# DW::Pay::all_shortnames +# +# ARGUMENTS: (none) +# +# RETURN: { typeid => shortname } hashref +# +sub all_shortnames { + my %names; + while ( my ( $typeid, $data ) = each %LJ::CAP ) { + # Avoid calling DW::Pay::type_is_valid a zillion times for the same typeid + $names{$typeid} = $data->{_account_type} + if DW::Pay::type_is_valid( $typeid ); + } + return \%names; } ################################################################################ @@ -173,7 +206,7 @@ sub get_account_type { confess 'account has no valid typeid' unless $typeid && $typeid > 0; confess "typeid $typeid not a valid account level" - unless $LJ::CAP{$typeid} && $LJ::CAP{$typeid}->{_account_type}; + unless DW::Pay::type_is_valid( $typeid ); return $LJ::CAP{$typeid}->{_account_type}; } @@ -191,7 +224,7 @@ sub get_account_type_name { confess 'account has no valid typeid' unless $typeid && $typeid > 0; confess "typeid $typeid not a valid account level" - unless $LJ::CAP{$typeid} && $LJ::CAP{$typeid}->{_visible_name}; + unless DW::Pay::type_is_valid( $typeid ); return $LJ::CAP{$typeid}->{_visible_name}; } @@ -679,3 +712,4 @@ sub get_db_writer { } 1; + diff -r f1b881e72e8d -r c557c814bf14 cgi-bin/DW/StatData/ActiveAccounts.pm --- a/cgi-bin/DW/StatData/ActiveAccounts.pm Wed Nov 25 04:18:51 2009 +0000 +++ b/cgi-bin/DW/StatData/ActiveAccounts.pm Wed Nov 25 05:14:57 2009 +0000 @@ -1,6 +1,7 @@ #!/usr/bin/perl # # DW::StatData::ActiveAccounts - Active accounts, by #days since last active +# and account level # # Authors: # Pau Amma <pauamma@cpan.org> @@ -38,7 +39,16 @@ use base 'DW::StatData'; sub category { "active" } sub name { "Active Accounts" } -sub keylist { [ qw( active_1d active_7d active_30d ) ] } + +my %key_to_days = ( active_1d => 1, active_7d => 7, active_30d => 30 ); +sub keylist { + my @levels = ( 'unknown', values %{DW::Pay::all_shortnames()} ); + my @keys = (); + foreach my $k ( keys %key_to_days ) { + push @keys, $k, map "$k-$_", @levels; + } + return \@keys; +} =head1 API @@ -48,33 +58,45 @@ Collects data for the following keys: =over -=item active_1d +=item active_1d, active_1d-I<< level name >> -Number of accounts active in the last 24 hours +Number of accounts active in the last 24 hours (total and for each account +level) -=item active_7d +=item active_7d, active_7d-I<< level name >> -Number of accounts active in the last 168 (7*24) hours +Number of accounts active in the last 168 (7*24) hours (total and for each +account level) -=item active_30d +=item active_30d, active_30d-I<< level name >> -Number of accounts active in the last 720 (30*24) hours +Number of accounts active in the last 720 (30*24) hours (total and for each +account level) =back +In the above, I<< level name >> is any of the account level names returned by +C<< DW::Pay::all_shortnames >> or "unknown". + =cut -my %key_to_days = ( active_1d => 1, active_7d => 7, active_30d => 30 ); sub collect { my ( $class, @keys ) = @_; my $max_days = 0; my %data; + my $shortnames = DW::Pay::all_shortnames(); + my @levels = ( '', 'unknown', values %$shortnames ); foreach my $k ( @keys ) { + my ( $keyprefix, $keylevel ) = split( '-', $k ); + $keylevel ||= ''; + die "Unknown statkey $k for $class" - unless exists $key_to_days{$k}; - $max_days = $key_to_days{$k} - if $max_days < $key_to_days{$k}; + unless exists $key_to_days{$keyprefix} + and grep { $_ eq $keylevel } @levels; + + $max_days = $key_to_days{$keyprefix} + if $max_days < $key_to_days{$keyprefix}; $data{$k} = 0; } @@ -82,17 +104,25 @@ sub collect { my ( $cid, $dbr ) = @_; # $cid isn't used my $sth = $dbr->prepare( qq{ - SELECT FLOOR((UNIX_TIMESTAMP()-timeactive)/86400) as days, COUNT(*) + SELECT FLOOR((UNIX_TIMESTAMP()-timeactive)/86400) as days, + accountlevel, COUNT(*) FROM clustertrack2 - WHERE timeactive > UNIX_TIMESTAMP()-? GROUP BY days } ); + WHERE timeactive > UNIX_TIMESTAMP()-? + GROUP BY days, accountlevel } ); $sth->execute( $max_days*86400 ); - while ( my ( $days, $active ) = $sth->fetchrow_array ) { + while ( my ( $days, $level, $active ) = $sth->fetchrow_array ) { + $level = ( defined $level ) ? $shortnames->{$level} : 'unknown'; # which day interval(s) does this fall in? # -- in last day, in last 7, in last 30? foreach my $k ( @keys ) { - $data{$k} += $active if $days < $key_to_days{$k}; + my ( $keyprefix, $keylevel ) = split( '-', $k ); + $keylevel ||= ''; + if ( $days < $key_to_days{$keyprefix} + && ( $keylevel eq $level || $keylevel eq '' ) ) { + $data{$k} += $active; + } } } } ); diff -r f1b881e72e8d -r c557c814bf14 cgi-bin/DW/StatData/PaidAccounts.pm --- a/cgi-bin/DW/StatData/PaidAccounts.pm Wed Nov 25 04:18:51 2009 +0000 +++ b/cgi-bin/DW/StatData/PaidAccounts.pm Wed Nov 25 05:14:57 2009 +0000 @@ -35,11 +35,12 @@ sub keylist { sub keylist { my @account_type_keys; my $default_typeid = DW::Pay::default_typeid(); + my $shortnames = DW::Pay::all_shortnames(); - foreach my $typeid ( keys %LJ::CAP ) { + while ( my ( $typeid, $name ) = each %$shortnames ) { next if $typeid == $default_typeid; - push @account_type_keys, $LJ::CAP{$typeid}->{_account_type} if $LJ::CAP{$typeid}->{_account_type}; + push @account_type_keys, $name; } return \@account_type_keys; @@ -71,19 +72,16 @@ sub collect { my $dbslow = LJ::get_dbh( 'slow' ) or die "Can't get slow role"; + my $default_typeid = DW::Pay::default_typeid(); my $sth = $dbslow->prepare( qq{ - SELECT typeid, count(*) FROM dw_paidstatus GROUP BY typeid + SELECT typeid, count(*) FROM dw_paidstatus WHERE typeid != ? GROUP BY typeid } ); - $sth->execute; + $sth->execute( $default_typeid ); - my $default_typeid = DW::Pay::default_typeid(); while ( my ( $typeid, $active ) = $sth->fetchrow_array ) { - next if $typeid == $default_typeid; - - my $account_type = $LJ::CAP{$typeid}->{_account_type}; - next unless defined $account_type and exists $data{$account_type}; - - $data{$account_type} = $active; + next unless DW::Pay::type_is_valid( $typeid ); + my $account_type = DW::Pay::type_shortname( $typeid ); + $data{$account_type} = $active if exists $data{$account_type}; } return \%data; @@ -92,8 +90,6 @@ sub collect { =head1 BUGS Trying to get the number of free accounts from dw_paidstatus will return an inaccurate number, because that only counts accounts which were paid at some point. So we do not collect stats for the default_typeid, which are free accounts for Dreamwidth. This makes assumptions, but I think not too out of line. - -Needs to refactor more of the logic into DW::Pay (or some kind of BusinessRule or hook, to take care of site-specific logic) =head1 AUTHORS --------------------------------------------------------------------------------