#!/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">&nbsp;</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 -%]&nbsp;[%- END -%]
    &nbsp;&nbsp;</td>
    <td class="person">
    [% names.$person %]&nbsp;(<a href="http://search.cpan.org/search?author=[% person %]">[% person %]</a>)&nbsp;&nbsp;
    ([% 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">&nbsp;</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