220 lines
8.3 KiB
Plaintext
Executable File
220 lines
8.3 KiB
Plaintext
Executable File
<?page
|
|
title=>Statistics
|
|
body<=
|
|
|
|
<?h1 <?sitename?> Statistics h1?>
|
|
<?p
|
|
The following statistics may be interesting for some of you. Note that for speed, most of this page is only updated every 24 hours. However, certain parts are live. Raw data can be picked up <a href="stats/stats.txt">here</a>.
|
|
p?>
|
|
<?hr?>
|
|
|
|
<?_code
|
|
|
|
use strict;
|
|
|
|
LJ::set_active_crumb('stats');
|
|
|
|
my $dbr = LJ::get_db_reader();
|
|
my $sth;
|
|
|
|
my $now = time();
|
|
my %stat = ();
|
|
|
|
$sth = $dbr->prepare("SELECT statcat, statkey, statval FROM stats WHERE statcat IN ('userinfo', 'client', 'age', 'gender', 'account', 'size')");
|
|
$sth->execute;
|
|
while ($_ = $sth->fetchrow_hashref) {
|
|
$stat{$_->{'statcat'}}->{$_->{'statkey'}} = $_->{'statval'};
|
|
}
|
|
|
|
unless (%stat) {
|
|
return "<?h1 Sorry... h1?><?p No statistics are available. If you're the administrator for this site, run <b>ljmaint.pl genstats</b>, or ideally, put it in cron to run nightly. p?>";
|
|
}
|
|
|
|
$sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='country' AND s.statcat='country' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15");
|
|
$sth->execute;
|
|
while ($_ = $sth->fetchrow_hashref) {
|
|
$stat{'country'}->{$_->{'item'}} = $_->{'statval'};
|
|
}
|
|
|
|
$sth = $dbr->prepare("SELECT c.item, s.statval FROM stats s, codes c WHERE c.type='state' AND s.statcat='stateus' AND s.statkey=c.code ORDER BY s.statval DESC LIMIT 15");
|
|
$sth->execute;
|
|
while ($_ = $sth->fetchrow_hashref) {
|
|
$stat{'state'}->{$_->{'item'}} = $_->{'statval'};
|
|
}
|
|
|
|
my $total = $stat{'userinfo'}->{'total'}+0;
|
|
my $usedever = $stat{'userinfo'}->{'updated'}+0;
|
|
my $used30 = $stat{'userinfo'}->{'updated_last30'}+0;
|
|
my $used7 = $stat{'userinfo'}->{'updated_last7'}+0;
|
|
my $usedlastday = $stat{'userinfo'}->{'updated_last1'}+0;
|
|
my $allow_getljnews = $stat{'userinfo'}->{'allow_getljnews'}+0;
|
|
my $active = $stat{'size'}->{'accounts_active'}+0;
|
|
|
|
my $ret = "";
|
|
$ret .= "<?h1 Users h1?>\n";
|
|
$ret .= "<?p How many users, and how many of those are active? p?> <ul>";
|
|
$ret .= "<li><b>Total accounts: </b> $total</li>\n";
|
|
$ret .= "<li><b>... active in some way: </b> $active</li>\n" if $active;
|
|
$ret .= "<li><b>... that have ever updated: </b> $usedever</li>\n";
|
|
$ret .= "<li><b>... updating in last 30 days: </b> $used30</li>\n";
|
|
$ret .= "<li><b>... updating in last 7 days: </b> $used7</li>\n";
|
|
$ret .= "<li><b>... updating in past 24 hours: </b> $usedlastday</li>\n";
|
|
$ret .= "</ul> \n";
|
|
|
|
$ret .= "<?h1 Gender h1?>\n";
|
|
$ret .= "<?p Are males or females more likely to maintain journals? p?><ul>";
|
|
{
|
|
my $male = $stat{'gender'}->{'M'}+0;
|
|
my $female = $stat{'gender'}->{'F'}+0;
|
|
my $tot = $male+$female;
|
|
$tot ||= 1;
|
|
$ret .= "<li><b>Male: </b> $male (" . sprintf("%0.1f", $male*100/($tot||1)) . "%)</li>";
|
|
$ret .= "<li><b>Female: </b> $female (" . sprintf("%0.1f", $female*100/($tot||1)) . "%)</li>";
|
|
}
|
|
$ret .= "<li><b>Unspecified: </b> " . ($stat{'gender'}->{'U'}+0) . "</li>";
|
|
$ret .= "</ul>\n";
|
|
|
|
LJ::run_hook('statspage', {
|
|
stat => \%stat,
|
|
ret => \$ret,
|
|
});
|
|
|
|
unless ($LJ::DISABLED{'stats-recentupdates'})
|
|
{
|
|
$ret .= "<?h1 Recent Updates h1?>\n";
|
|
$ret .= "<?p The following are the 10 most recently updated journals: p?><ul>";
|
|
$sth = $dbr->prepare("SELECT u.user, u.name, uu.timeupdate FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 30 DAY) ORDER BY uu.timeupdate DESC LIMIT 10");
|
|
$sth->execute;
|
|
my $ct;
|
|
while (my ($iuser, $iname, $itime) = $sth->fetchrow_array) {
|
|
$ret .= "<li><a href='/users/$iuser/'><?_eh $iname _eh?></a>, $itime</li>\n";
|
|
$ct++;
|
|
}
|
|
$ret .= "<li><i>stat not available</i></li>" unless $ct;
|
|
$ret .= "</ul> \n";
|
|
}
|
|
|
|
unless ($LJ::DISABLED{'stats-newjournals'})
|
|
{
|
|
$ret .= "<?h1 New Journals h1?>\n";
|
|
$ret .= "<?p The following are the 10 most recently created journals. It's very likely these users haven't modified their journals much, and probably haven't written much in them yet either... p?><ul>";
|
|
$sth = $dbr->prepare("SELECT u.user, u.name, uu.timeupdate FROM user u, userusage uu WHERE u.userid=uu.userid AND uu.timeupdate IS NOT NULL ORDER BY uu.timecreate DESC LIMIT 10");
|
|
$sth->execute;
|
|
my $ct;
|
|
while (my ($iuser, $iname, $itime) = $sth->fetchrow_array) {
|
|
$ret .= "<li><a href='/users/$iuser/'><?_eh $iname _eh?></a>, $itime</li>\n";
|
|
$ct++;
|
|
}
|
|
$ret .= "<li><i>stat not available</i></li>" unless $ct;
|
|
$ret .= "</ul>\n";
|
|
}
|
|
|
|
$ret .= "<?h1 Demographics h1?>\n";
|
|
{
|
|
$ret .= "<?p The following are the 15 most popular countries $LJ::SITENAMESHORT is used in: p?><ul>";
|
|
my $ct;
|
|
foreach my $key (sort { $stat{'country'}->{$b} <=> $stat{'country'}->{$a} }
|
|
keys %{$stat{'country'}})
|
|
{
|
|
$ret .= "<li><b>$key</b> - $stat{'country'}->{$key}</li>\n";
|
|
$ct++;
|
|
}
|
|
$ret .= "<li><i>stat not available</i></li>" unless $ct;
|
|
$ret .= "</ul>\n";
|
|
}
|
|
|
|
{
|
|
$ret .= "The following are the 15 most popular U.S. states $LJ::SITENAMESHORT is used in: <ul>";
|
|
my $ct;
|
|
foreach my $key (sort { $stat{'state'}->{$b} <=> $stat{'state'}->{$a} } keys %{$stat{'state'}})
|
|
{
|
|
$ret .= "<li><b>$key</b> - $stat{'state'}->{$key}</li>\n";
|
|
$ct++;
|
|
}
|
|
$ret .= "<li><i>stat not available</i></li>" unless $ct;
|
|
$ret .= "</ul> \n";
|
|
}
|
|
|
|
# ages
|
|
my %age = ();
|
|
my $maxage = 1;
|
|
foreach my $key (keys %{$stat{'age'}}) {
|
|
$age{$key} = $stat{'age'}->{$key};
|
|
if ($stat{'age'}->{$key} > $maxage) { $maxage = $stat{'age'}->{$key}; }
|
|
}
|
|
my @ages = grep { $_ >= 13 && $_ <= 55 } sort { $a <=> $b } sort keys %age;
|
|
if (@ages) {
|
|
$ret .= "<?h1 Age Distribution h1?><?p The following shows the age distribution " .
|
|
"of $LJ::SITENAMESHORT users: p?>\n";
|
|
$ret .= "<table>\n";
|
|
my $lastage = 0;
|
|
foreach my $age (@ages) {
|
|
my $width = int(400 * $age{$age}/$maxage);
|
|
$ret .= "<tr><td align='right'><b>$age</b></td><td>$age{$age}</td><td><img src=\"/img/bluedot.gif\" height='10' width='$width' /></td></tr>\n";
|
|
$lastage = $_;
|
|
}
|
|
$ret .= "</table>\n";
|
|
}
|
|
|
|
# clients (if enabled)
|
|
unless ($LJ::DISABLED{'clientversionlog'}) {
|
|
|
|
### sum up clients over different versions
|
|
foreach my $c (keys %{$stat{'client'}}) {
|
|
next unless ($c =~ /^(.+?)\//);
|
|
$stat{'clientname'}->{$1} += $stat{'client'}->{$c};
|
|
}
|
|
|
|
my $out;
|
|
foreach my $cn (sort { $stat{'clientname'}->{$b} <=> $stat{'clientname'}->{$a} }
|
|
keys %{$stat{'clientname'}})
|
|
{
|
|
last unless $stat{'clientname'}->{$cn} >= 50;
|
|
$out .= "<tr valign='top'><td><font size='+1'><b>$stat{'clientname'}->{$cn}</b></font></td>".
|
|
"<td><b>" . LJ::ehtml($cn) . "</b><br />\n";
|
|
$out .= "<font size='-1'>\n";
|
|
foreach my $c (sort grep { /^\Q$cn\E\// } keys %{$stat{'client'}}) {
|
|
my $count = $stat{'client'}->{$c};
|
|
$c =~ s/^\Q$cn\E\///;
|
|
$out .= LJ::ehtml($c) . " ($count), ";
|
|
}
|
|
chop $ret; chop $ret; # remove trailing ", "
|
|
$out .= "</font>\n";
|
|
$out .= "</td></tr>\n";
|
|
}
|
|
|
|
if ($out) {
|
|
$ret .= "<?h1 Client Usage h1?><?p How people update their journals (over the last 30 days): p?>\n";
|
|
$ret .= "<table cellpadding='3'>\n";
|
|
$ret .= $out;
|
|
$ret .= "</table>\n";
|
|
}
|
|
}
|
|
|
|
|
|
# return early, since the graphs below are pretty much broken now
|
|
# with index changes. FIXME: make alternate means to generate stats
|
|
return $ret;
|
|
|
|
### graphs!
|
|
$ret .= "<?h1 Pretty Graphs! h1?><?p These are the most fun, aren't they? p?>";
|
|
|
|
$ret .= "<?h2 Journal entries -- last 60 days h2?><?p How often do people post over the last 60 days? p?>";
|
|
$ret .= "<p align='center'><img src=\"stats/postsbyday.png\" width='520' height='350' /></p>";
|
|
|
|
$ret .= "<?h2 Journal entries -- by week, ever h2?><?p What's the week-to-week trend? p?>";
|
|
$ret .= "<p align='center'><img src=\"stats/postsbyweek.png\" width='520' height='350' /></p>";
|
|
|
|
$ret .= "<?h2 New accounts -- last 60 days h2?><?p How fast are we growing? p?>";
|
|
$ret .= "<p align='center'><img src=\"stats/newbyday.png\" width='520' height='350' /></p>";
|
|
|
|
return $ret;
|
|
|
|
_code?>
|
|
|
|
<=body
|
|
page?><?_c <LJDEP>
|
|
link: htdocs/stats/, htdocs/support/faqbrowse.bml
|
|
img: htdocs/img/bluedot.gif, htdocs/stats/postsbyday.png, htdocs/stats/postsbyweek.png, htdocs/stats/newbyday.png
|
|
</LJDEP> _c?>
|