#!/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">&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">
    <a name="[% person %]" ></a>
    [% 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 %]

[% END %]


syntax highlighted by Code2HTML, v. 0.9