#!/usr/local/bin/perl -w
# import away
use strict;
use warnings;
use Template;
use LWP::Simple;
use Parse::CPAN::Packages;
use File::Copy;
# r00ts!
my $root = "/usr/local/www";
# fetch the list of names
# cpanscore is just a hash of CPANID => 'real name'
our %names;
require "$root/etc/cpanscorerc";
# gah, Parse::CPAN::Packages should really take a filehandle
my $url = "http://ftp.funet.fi/pub/languages/perl/CPAN/modules/02packages.details.txt.gz";
my $rc = mirror( $url, "tmp/packages.gz" );
# $rc == RC_NOT_MODIFIED and exit;
!(is_success($rc) || $rc == RC_NOT_MODIFIED) and die "Could not fetch package\n";
system("gzip -dc /tmp/packages.gz > /tmp/packages");
my $p = Parse::CPAN::Packages->new("/tmp/packages");
# the total number of modules on cpan
my $total = 0;
# the total lpm number
my $lpmtotal = 0;
# try and keep track of stuff
my %seen;
my %people;
my %totalpeople;
# are we going to rank everybody?
my $everything = (@ARGV && $ARGV[0] eq '-e'); # everything i.e do the whole of CPAN
# loop through all the modules
foreach my $dist ($p->distributions) {
my $dist_name;
next unless $dist_name = $dist->dist;
next unless $dist = $p->latest_distribution($dist_name);
my $author = $dist->cpanid or next;
# old version
next if $seen{$dist_name}++;
$total++;
# increase the hash of the total number of people
# this a hack and a bit redundant but cleaner
# than using %people and then skipping anything
# that doesn't have any modules
$totalpeople{$author} = 1;
# not london.pm
next unless ($everything || (grep{/^$author$/} keys %names));
$lpmtotal++;
$people{ $author }->{total}++;
push @{$people{ $author }{modules}}, $dist_name;
}
# get the total number of people
my $totalpeople = keys %totalpeople;
my $lpmpeople = keys %names;
# sort by number then name
my @order = sort funky_sort keys %people;
# to stop it getting ridiculously large
if ($everything) {
@order = grep { $people{$_}->{total}>1 } @order;
}
sub funky_sort ()
{
my $diff = $people{$b}->{total} - $people{$a}->{total};
$diff = lc($names{$a}) cmp lc($names{$b}) if ($diff == 0 && !$everything);
return $diff;
}
# now print it all out
my $template = join "", <DATA>;
my $tt = Template->new({
INCLUDE_PATH => "$root/lib",
PRE_PROCESS => "config/main",
}) || die $Template::ERROR, "\n";
my $vars = { people => \%people,
totalpeople => $totalpeople,
total => $total,
lpmtotal => $lpmtotal,
time => scalar localtime(),
order => \@order,
names => \%names,
lpmpeople => $lpmpeople,
percent => $lpmtotal*100/$total,
ppl_percent => $lpmpeople*100/$totalpeople,
all => $everything,
rooturl => "../",
};
$tt->process(\$template, $vars) || die $tt->error(), "\n";
__DATA__
[% page.title = "CPAN Leaderboard" %]
[% WRAPPER site/html + site/layout %]
<p>
The [%- IF !all -%]<a href="http://london.pm.org/">London.pm</a> [%- END -%]CPAN Leaderboard
(generated from 02packages.details.txt.gz on [% time %])
</p>
<p>
Contributors are ranked by number of modules and then by name
</p>
<p>
The code that does it is <a href="cpanscore.html">here</a> - it's ugly.
</p>
<p>
enjoy ...
</p>
<p>
<a href="mailto:simon@thegestalt.org">simon</a>
</p>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td colspan="3" class="top"> </td>
</tr>
[%- SET lastscore = 0 -%]
[%- SET rcounter = 0 -%]
[%- SET pcounter = 0 -%]
[% FOREACH person = order %]
[%- rcounter=1+rcounter -%]
[%- SET nmods = people.$person.total -%]
<tr>
<td class="rank">
[%- IF lastscore != nmods -%]
[%- pcounter = rcounter -%]
[%- pcounter -%]
[%- ELSE -%]
[%- pcounter -%]=
[%- END -%]
[%- lastscore = nmods -%]
[%- IF pcounter<10 -%] [%- END -%]
</td>
<td class="person">
<a name="[% person %]" ></a>
[% names.$person %] (<a href="http://search.cpan.org/search?author=[% person %]">[% person %]</a>)
([% nmods %])
</td>
<td class="modules">
[%- FOREACH module = people.$person.modules.sort -%]
<a href="http://search.cpan.org/dist/[%- module -%]/">[%- module -%]</a>[%- IF module != people.$person.modules.sort.last -%], [%- END -%]
[%- END -%]
</td>
</tr>
[% END %]
<tr>
<td colspan="3" class="bottom"> </td>
</td>
</table>
[% IF !all %]
London.pm contributed :
<p>
[% lpmtotal %] of [% total %] packages ([% percent | format("%.2f") %]%)
on CPAN<br />
and constitute [% lpmpeople %] of all [% totalpeople %] authors ([% ppl_percent | format("%.2f") %]%).
</p>
[% END %]
[% END %]
syntax highlighted by Code2HTML, v. 0.9