#!/usr/local/bin/perl -w
# import away
use strict;
use warnings;
use Template;
use LWP::Simple;
use Parse::CPAN::Packages;
use File::Copy;
# fetch the list of names
our %names;
require '.cpanscorerc';
# gah, Parse::CPAN::Packages should really take a filehandle
my $url = "http://ftp.mirror.ac.uk/sites/ftp.funet.fi/pub/languages/perl/CPAN/modules/02packages.details.txt.gz";
my $rc = mirror( $url, "/tmp/packages.gz" );
!(is_success($rc)) and exit;
$rc == RC_NOT_MODIFIED and exit;
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 $author = $dist->cpanid or next;
next unless $dist = $dist->dist;
# old version
next if $seen{$dist}++;
$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;
}
# 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 = $names{$a} cmp $names{$b} if ($diff == 0 && !$everything);
return $diff;
}
# now print it all out
my $template = join "", <DATA>;
my $tt = Template->new || 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,
};
$tt->process(\$template, $vars) || die $tt->error(), "\n";
__DATA__
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>[%- IF !all -%]London.pm [%- END -%]CPAN Leaderboard</title>
<style type="text/css">
body {
background: #fff;
color: #000
}
p, td {
font-family: Geneva, MS Sans Serif, Helvetica, Arial, sans-serif;
}
.rank {
width: 3em;
font-size: small;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
vertical-align: top
}
.person {
font-size: small;
border: 1px solid #ccc;
padding: 10px;
vertical-align: top
}
.modules {
font-size: small;
border-top: 1px solid #ccc;
padding-top: 5px;
border-left: 1px solid #ccc;
padding-left: 5px;
border-bottom: 1px solid #ccc;
padding-bottom: 20px
}
.top {
border-bottom: 1px solid #ccc
}
.bottom {
border-top: 1px solid #ccc
}
</style>
</head>
<body>
<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">
[% 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 %]
</body>
</html>
syntax highlighted by Code2HTML, v. 0.9.1